LCOV - code coverage report
Current view: top level - test/cctest - test-api.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 13029 13279 98.1 %
Date: 2017-10-20 Functions: 1040 1122 92.7 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include <climits>
      29             : #include <csignal>
      30             : #include <map>
      31             : #include <memory>
      32             : #include <string>
      33             : 
      34             : #include "test/cctest/test-api.h"
      35             : 
      36             : #if V8_OS_POSIX
      37             : #include <unistd.h>  // NOLINT
      38             : #endif
      39             : 
      40             : #include "include/v8-util.h"
      41             : #include "src/api.h"
      42             : #include "src/arguments.h"
      43             : #include "src/base/platform/platform.h"
      44             : #include "src/code-stubs.h"
      45             : #include "src/compilation-cache.h"
      46             : #include "src/debug/debug.h"
      47             : #include "src/execution.h"
      48             : #include "src/futex-emulation.h"
      49             : #include "src/heap/incremental-marking.h"
      50             : #include "src/heap/local-allocator.h"
      51             : #include "src/lookup.h"
      52             : #include "src/objects-inl.h"
      53             : #include "src/parsing/preparse-data.h"
      54             : #include "src/profiler/cpu-profiler.h"
      55             : #include "src/unicode-inl.h"
      56             : #include "src/utils.h"
      57             : #include "src/vm-state.h"
      58             : #include "test/cctest/heap/heap-tester.h"
      59             : #include "test/cctest/heap/heap-utils.h"
      60             : 
      61             : static const bool kLogThreading = false;
      62             : 
      63             : using ::v8::Array;
      64             : using ::v8::Boolean;
      65             : using ::v8::BooleanObject;
      66             : using ::v8::Context;
      67             : using ::v8::Extension;
      68             : using ::v8::Function;
      69             : using ::v8::FunctionTemplate;
      70             : using ::v8::HandleScope;
      71             : using ::v8::Local;
      72             : using ::v8::Maybe;
      73             : using ::v8::Message;
      74             : using ::v8::MessageCallback;
      75             : using ::v8::Module;
      76             : using ::v8::Name;
      77             : using ::v8::None;
      78             : using ::v8::Object;
      79             : using ::v8::ObjectTemplate;
      80             : using ::v8::Persistent;
      81             : using ::v8::PropertyAttribute;
      82             : using ::v8::Script;
      83             : using ::v8::StackTrace;
      84             : using ::v8::String;
      85             : using ::v8::Symbol;
      86             : using ::v8::TryCatch;
      87             : using ::v8::Undefined;
      88             : using ::v8::V8;
      89             : using ::v8::Value;
      90             : 
      91             : 
      92             : #define THREADED_PROFILED_TEST(Name)                                 \
      93             :   static void Test##Name();                                          \
      94             :   TEST(Name##WithProfiler) {                                         \
      95             :     RunWithProfiler(&Test##Name);                                    \
      96             :   }                                                                  \
      97             :   THREADED_TEST(Name)
      98             : 
      99             : 
     100          75 : void RunWithProfiler(void (*test)()) {
     101          75 :   LocalContext env;
     102         150 :   v8::HandleScope scope(env->GetIsolate());
     103          75 :   v8::Local<v8::String> profile_name = v8_str("my_profile1");
     104          75 :   v8::CpuProfiler* cpu_profiler = v8::CpuProfiler::New(env->GetIsolate());
     105          75 :   cpu_profiler->StartProfiling(profile_name);
     106          75 :   (*test)();
     107          75 :   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
     108         150 :   cpu_profiler->Dispose();
     109          75 : }
     110             : 
     111             : 
     112             : static int signature_callback_count;
     113             : static Local<Value> signature_expected_receiver;
     114        3900 : static void IncrementingSignatureCallback(
     115       28080 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     116        3900 :   ApiTestFuzzer::Fuzz();
     117        3900 :   signature_callback_count++;
     118       11700 :   CHECK(signature_expected_receiver->Equals(
     119             :                                        args.GetIsolate()->GetCurrentContext(),
     120             :                                        args.Holder())
     121             :             .FromJust());
     122       11700 :   CHECK(signature_expected_receiver->Equals(
     123             :                                        args.GetIsolate()->GetCurrentContext(),
     124             :                                        args.This())
     125             :             .FromJust());
     126             :   v8::Local<v8::Array> result =
     127        3900 :       v8::Array::New(args.GetIsolate(), args.Length());
     128       10920 :   for (int i = 0; i < args.Length(); i++) {
     129        6240 :     CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
     130             :                       v8::Integer::New(args.GetIsolate(), i), args[i])
     131             :               .FromJust());
     132             :   }
     133             :   args.GetReturnValue().Set(result);
     134        3900 : }
     135             : 
     136             : 
     137         215 : static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
     138             :   info.GetReturnValue().Set(42);
     139         215 : }
     140             : 
     141             : 
     142             : // Tests that call v8::V8::Dispose() cannot be threaded.
     143       23723 : UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
     144           5 :   CHECK(v8::V8::Initialize());
     145           5 :   CHECK(v8::V8::Dispose());
     146           5 : }
     147             : 
     148             : 
     149             : // Tests that call v8::V8::Dispose() cannot be threaded.
     150       23723 : UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
     151           5 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     152          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     153          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     154          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     155          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     156           5 : }
     157             : 
     158             : // Tests that Smi::kZero is set up properly.
     159       23723 : UNINITIALIZED_TEST(SmiZero) { CHECK_EQ(i::Smi::kZero, i::Smi::kZero); }
     160             : 
     161       23724 : THREADED_TEST(Handles) {
     162           6 :   v8::HandleScope scope(CcTest::isolate());
     163             :   Local<Context> local_env;
     164             :   {
     165           6 :     LocalContext env;
     166           6 :     local_env = env.local();
     167             :   }
     168             : 
     169             :   // Local context should still be live.
     170           6 :   CHECK(!local_env.IsEmpty());
     171           6 :   local_env->Enter();
     172             : 
     173           6 :   v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
     174           6 :   CHECK(!undef.IsEmpty());
     175           6 :   CHECK(undef->IsUndefined());
     176             : 
     177             :   const char* source = "1 + 2 + 3";
     178           6 :   Local<Script> script = v8_compile(source);
     179           6 :   CHECK_EQ(6, v8_run_int32value(script));
     180             : 
     181           6 :   local_env->Exit();
     182           6 : }
     183             : 
     184             : 
     185       23724 : THREADED_TEST(IsolateOfContext) {
     186           6 :   v8::HandleScope scope(CcTest::isolate());
     187           6 :   v8::Local<Context> env = Context::New(CcTest::isolate());
     188             : 
     189           6 :   CHECK(!env->GetIsolate()->InContext());
     190           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     191           6 :   env->Enter();
     192           6 :   CHECK(env->GetIsolate()->InContext());
     193           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     194           6 :   env->Exit();
     195           6 :   CHECK(!env->GetIsolate()->InContext());
     196           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     197           6 : }
     198             : 
     199         420 : static void TestSignatureLooped(const char* operation, Local<Value> receiver,
     200             :                                 v8::Isolate* isolate) {
     201             :   i::ScopedVector<char> source(200);
     202             :   i::SNPrintF(source,
     203             :               "for (var i = 0; i < 10; i++) {"
     204             :               "  %s"
     205             :               "}",
     206         420 :               operation);
     207         420 :   signature_callback_count = 0;
     208         420 :   signature_expected_receiver = receiver;
     209             :   bool expected_to_throw = receiver.IsEmpty();
     210         840 :   v8::TryCatch try_catch(isolate);
     211             :   CompileRun(source.start());
     212         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     213         420 :   if (!expected_to_throw) {
     214         300 :     CHECK_EQ(10, signature_callback_count);
     215             :   } else {
     216         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     217             :               ->Equals(isolate->GetCurrentContext(),
     218             :                        try_catch.Exception()
     219             :                            ->ToString(isolate->GetCurrentContext())
     220             :                            .ToLocalChecked())
     221             :               .FromJust());
     222             :   }
     223         420 : }
     224             : 
     225         420 : static void TestSignatureOptimized(const char* operation, Local<Value> receiver,
     226             :                                    v8::Isolate* isolate) {
     227             :   i::ScopedVector<char> source(200);
     228             :   i::SNPrintF(source,
     229             :               "function test() {"
     230             :               "  %s"
     231             :               "}"
     232             :               "try { test() } catch(e) {}"
     233             :               "try { test() } catch(e) {}"
     234             :               "%%OptimizeFunctionOnNextCall(test);"
     235             :               "test()",
     236         420 :               operation);
     237         420 :   signature_callback_count = 0;
     238         420 :   signature_expected_receiver = receiver;
     239             :   bool expected_to_throw = receiver.IsEmpty();
     240         840 :   v8::TryCatch try_catch(isolate);
     241             :   CompileRun(source.start());
     242         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     243         420 :   if (!expected_to_throw) {
     244         300 :     CHECK_EQ(3, signature_callback_count);
     245             :   } else {
     246         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     247             :               ->Equals(isolate->GetCurrentContext(),
     248             :                        try_catch.Exception()
     249             :                            ->ToString(isolate->GetCurrentContext())
     250             :                            .ToLocalChecked())
     251             :               .FromJust());
     252             :   }
     253         420 : }
     254             : 
     255         420 : static void TestSignature(const char* operation, Local<Value> receiver,
     256             :                           v8::Isolate* isolate) {
     257         420 :   TestSignatureLooped(operation, receiver, isolate);
     258         420 :   TestSignatureOptimized(operation, receiver, isolate);
     259         420 : }
     260             : 
     261       23724 : THREADED_TEST(ReceiverSignature) {
     262           6 :   i::FLAG_allow_natives_syntax = true;
     263           6 :   LocalContext env;
     264           6 :   v8::Isolate* isolate = env->GetIsolate();
     265          12 :   v8::HandleScope scope(isolate);
     266             :   // Setup templates.
     267           6 :   v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
     268           6 :   v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
     269             :   v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
     270           6 :       isolate, IncrementingSignatureCallback, Local<Value>(), sig);
     271             :   v8::Local<v8::FunctionTemplate> callback =
     272           6 :       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
     273           6 :   v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
     274           6 :   sub_fun->Inherit(fun);
     275             :   v8::Local<v8::FunctionTemplate> direct_sub_fun =
     276           6 :       v8::FunctionTemplate::New(isolate);
     277           6 :   direct_sub_fun->Inherit(fun);
     278             :   v8::Local<v8::FunctionTemplate> unrel_fun =
     279           6 :       v8::FunctionTemplate::New(isolate);
     280             :   // Install properties.
     281           6 :   v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
     282          12 :   fun_proto->Set(v8_str("prop_sig"), callback_sig);
     283          12 :   fun_proto->Set(v8_str("prop"), callback);
     284             :   fun_proto->SetAccessorProperty(
     285          12 :       v8_str("accessor_sig"), callback_sig, callback_sig);
     286          12 :   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
     287             :   // Instantiate templates.
     288             :   Local<Value> fun_instance =
     289          18 :       fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     290             :   Local<Value> sub_fun_instance =
     291          18 :       sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     292             :   // Instance template with properties.
     293             :   v8::Local<v8::ObjectTemplate> direct_instance_templ =
     294           6 :       direct_sub_fun->InstanceTemplate();
     295          12 :   direct_instance_templ->Set(v8_str("prop_sig"), callback_sig);
     296          12 :   direct_instance_templ->Set(v8_str("prop"), callback);
     297             :   direct_instance_templ->SetAccessorProperty(v8_str("accessor_sig"),
     298          12 :                                              callback_sig, callback_sig);
     299             :   direct_instance_templ->SetAccessorProperty(v8_str("accessor"), callback,
     300          12 :                                              callback);
     301             :   Local<Value> direct_instance =
     302           6 :       direct_instance_templ->NewInstance(env.local()).ToLocalChecked();
     303             :   // Setup global variables.
     304          36 :   CHECK(env->Global()
     305             :             ->Set(env.local(), v8_str("Fun"),
     306             :                   fun->GetFunction(env.local()).ToLocalChecked())
     307             :             .FromJust());
     308          42 :   CHECK(env->Global()
     309             :             ->Set(env.local(), v8_str("UnrelFun"),
     310             :                   unrel_fun->GetFunction(env.local()).ToLocalChecked())
     311             :             .FromJust());
     312          30 :   CHECK(env->Global()
     313             :             ->Set(env.local(), v8_str("fun_instance"), fun_instance)
     314             :             .FromJust());
     315          30 :   CHECK(env->Global()
     316             :             ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
     317             :             .FromJust());
     318          30 :   CHECK(env->Global()
     319             :             ->Set(env.local(), v8_str("direct_instance"), direct_instance)
     320             :             .FromJust());
     321             :   CompileRun(
     322             :       "var accessor_sig_key = 'accessor_sig';"
     323             :       "var accessor_key = 'accessor';"
     324             :       "var prop_sig_key = 'prop_sig';"
     325             :       "var prop_key = 'prop';"
     326             :       ""
     327             :       "function copy_props(obj) {"
     328             :       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
     329             :       "  var source = Fun.prototype;"
     330             :       "  for (var i in keys) {"
     331             :       "    var key = keys[i];"
     332             :       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
     333             :       "    Object.defineProperty(obj, key, desc);"
     334             :       "  }"
     335             :       "}"
     336             :       ""
     337             :       "var plain = {};"
     338             :       "copy_props(plain);"
     339             :       "var unrelated = new UnrelFun();"
     340             :       "copy_props(unrelated);"
     341             :       "var inherited = { __proto__: fun_instance };"
     342             :       "var inherited_direct = { __proto__: direct_instance };");
     343             :   // Test with and without ICs
     344             :   const char* test_objects[] = {
     345             :       "fun_instance", "sub_fun_instance", "direct_instance", "plain",
     346           6 :       "unrelated",    "inherited",        "inherited_direct"};
     347             :   unsigned bad_signature_start_offset = 3;
     348          48 :   for (unsigned i = 0; i < arraysize(test_objects); i++) {
     349             :     i::ScopedVector<char> source(200);
     350             :     i::SNPrintF(
     351          42 :         source, "var test_object = %s; test_object", test_objects[i]);
     352          42 :     Local<Value> test_object = CompileRun(source.start());
     353          42 :     TestSignature("test_object.prop();", test_object, isolate);
     354          42 :     TestSignature("test_object.accessor;", test_object, isolate);
     355          42 :     TestSignature("test_object[accessor_key];", test_object, isolate);
     356          42 :     TestSignature("test_object.accessor = 1;", test_object, isolate);
     357          42 :     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
     358          42 :     if (i >= bad_signature_start_offset) test_object = Local<Value>();
     359          42 :     TestSignature("test_object.prop_sig();", test_object, isolate);
     360          42 :     TestSignature("test_object.accessor_sig;", test_object, isolate);
     361          42 :     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
     362          42 :     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
     363          42 :     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
     364           6 :   }
     365           6 : }
     366             : 
     367             : 
     368       23724 : THREADED_TEST(HulIgennem) {
     369           6 :   LocalContext env;
     370           6 :   v8::Isolate* isolate = env->GetIsolate();
     371          12 :   v8::HandleScope scope(isolate);
     372             :   v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
     373           6 :   Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
     374           6 :   char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
     375           6 :   undef_str->WriteUtf8(value);
     376           6 :   CHECK_EQ(0, strcmp(value, "undefined"));
     377           6 :   i::DeleteArray(value);
     378           6 : }
     379             : 
     380             : 
     381       23724 : THREADED_TEST(Access) {
     382           6 :   LocalContext env;
     383           6 :   v8::Isolate* isolate = env->GetIsolate();
     384          12 :   v8::HandleScope scope(isolate);
     385           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
     386             :   Local<Value> foo_before =
     387          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     388           6 :   CHECK(foo_before->IsUndefined());
     389           6 :   Local<String> bar_str = v8_str("bar");
     390          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
     391             :   Local<Value> foo_after =
     392          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     393           6 :   CHECK(!foo_after->IsUndefined());
     394           6 :   CHECK(foo_after->IsString());
     395          12 :   CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
     396             : 
     397          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).ToChecked());
     398             :   bool result;
     399          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).To(&result));
     400          12 :   CHECK(result);
     401           6 : }
     402             : 
     403             : 
     404       23724 : THREADED_TEST(AccessElement) {
     405           6 :   LocalContext env;
     406          12 :   v8::HandleScope scope(env->GetIsolate());
     407           6 :   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
     408           6 :   Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
     409           6 :   CHECK(before->IsUndefined());
     410           6 :   Local<String> bar_str = v8_str("bar");
     411          12 :   CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
     412           6 :   Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
     413           6 :   CHECK(!after->IsUndefined());
     414           6 :   CHECK(after->IsString());
     415          12 :   CHECK(bar_str->Equals(env.local(), after).FromJust());
     416             : 
     417             :   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
     418          24 :   CHECK(v8_str("a")
     419             :             ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
     420             :             .FromJust());
     421          24 :   CHECK(v8_str("b")
     422             :             ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
     423           6 :             .FromJust());
     424           6 : }
     425             : 
     426             : 
     427       23724 : THREADED_TEST(Script) {
     428           6 :   LocalContext env;
     429          12 :   v8::HandleScope scope(env->GetIsolate());
     430             :   const char* source = "1 + 2 + 3";
     431           6 :   Local<Script> script = v8_compile(source);
     432          12 :   CHECK_EQ(6, v8_run_int32value(script));
     433           6 : }
     434             : 
     435             : 
     436             : class TestResource: public String::ExternalStringResource {
     437             :  public:
     438             :   explicit TestResource(uint16_t* data, int* counter = nullptr,
     439             :                         bool owning_data = true)
     440       17942 :       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
     441     3064651 :     while (data[length_]) ++length_;
     442             :   }
     443             : 
     444       35878 :   ~TestResource() {
     445       17942 :     if (owning_data_) i::DeleteArray(data_);
     446       17942 :     if (counter_ != nullptr) ++*counter_;
     447       35878 :   }
     448             : 
     449       57060 :   const uint16_t* data() const {
     450       57060 :     return data_;
     451             :   }
     452             : 
     453       53760 :   size_t length() const {
     454       53760 :     return length_;
     455             :   }
     456             : 
     457             :  private:
     458             :   uint16_t* data_;
     459             :   size_t length_;
     460             :   int* counter_;
     461             :   bool owning_data_;
     462             : };
     463             : 
     464             : 
     465             : class TestOneByteResource : public String::ExternalOneByteStringResource {
     466             :  public:
     467             :   explicit TestOneByteResource(const char* data, int* counter = nullptr,
     468             :                                size_t offset = 0)
     469             :       : orig_data_(data),
     470          10 :         data_(data + offset),
     471          70 :         length_(strlen(data) - offset),
     472         150 :         counter_(counter) {}
     473             : 
     474         130 :   ~TestOneByteResource() {
     475          70 :     i::DeleteArray(orig_data_);
     476          70 :     if (counter_ != nullptr) ++*counter_;
     477         130 :   }
     478             : 
     479         202 :   const char* data() const {
     480         202 :     return data_;
     481             :   }
     482             : 
     483         117 :   size_t length() const {
     484         117 :     return length_;
     485             :   }
     486             : 
     487             :  private:
     488             :   const char* orig_data_;
     489             :   const char* data_;
     490             :   size_t length_;
     491             :   int* counter_;
     492             : };
     493             : 
     494             : 
     495       23724 : THREADED_TEST(ScriptUsingStringResource) {
     496           6 :   int dispose_count = 0;
     497             :   const char* c_source = "1 + 2 * 3";
     498           6 :   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
     499             :   {
     500           6 :     LocalContext env;
     501          12 :     v8::HandleScope scope(env->GetIsolate());
     502           6 :     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
     503             :     Local<String> source =
     504           6 :         String::NewExternalTwoByte(env->GetIsolate(), resource)
     505           6 :             .ToLocalChecked();
     506           6 :     Local<Script> script = v8_compile(source);
     507          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     508           6 :     CHECK(value->IsNumber());
     509          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     510           6 :     CHECK(source->IsExternal());
     511           6 :     CHECK_EQ(resource,
     512             :              static_cast<TestResource*>(source->GetExternalStringResource()));
     513             :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     514           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     515             :              source->GetExternalStringResourceBase(&encoding));
     516           6 :     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
     517           6 :     CcTest::CollectAllGarbage();
     518          12 :     CHECK_EQ(0, dispose_count);
     519             :   }
     520           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     521           6 :   CcTest::CollectAllAvailableGarbage();
     522           6 :   CHECK_EQ(1, dispose_count);
     523           6 : }
     524             : 
     525             : 
     526       23724 : THREADED_TEST(ScriptUsingOneByteStringResource) {
     527           6 :   int dispose_count = 0;
     528             :   const char* c_source = "1 + 2 * 3";
     529             :   {
     530           6 :     LocalContext env;
     531          12 :     v8::HandleScope scope(env->GetIsolate());
     532             :     TestOneByteResource* resource =
     533           6 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
     534             :     Local<String> source =
     535           6 :         String::NewExternalOneByte(env->GetIsolate(), resource)
     536           6 :             .ToLocalChecked();
     537           6 :     CHECK(source->IsExternalOneByte());
     538           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     539             :              source->GetExternalOneByteStringResource());
     540             :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     541           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     542             :              source->GetExternalStringResourceBase(&encoding));
     543           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     544           6 :     Local<Script> script = v8_compile(source);
     545          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     546           6 :     CHECK(value->IsNumber());
     547          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     548           6 :     CcTest::CollectAllGarbage();
     549          12 :     CHECK_EQ(0, dispose_count);
     550             :   }
     551           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     552           6 :   CcTest::CollectAllAvailableGarbage();
     553           6 :   CHECK_EQ(1, dispose_count);
     554           6 : }
     555             : 
     556             : 
     557       23724 : THREADED_TEST(ScriptMakingExternalString) {
     558           6 :   int dispose_count = 0;
     559           6 :   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
     560             :   {
     561           6 :     LocalContext env;
     562          12 :     v8::HandleScope scope(env->GetIsolate());
     563             :     Local<String> source =
     564             :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     565           6 :                                v8::NewStringType::kNormal)
     566           6 :             .ToLocalChecked();
     567             :     // Trigger GCs so that the newly allocated string moves to old gen.
     568           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     569           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     570           6 :     CHECK(!source->IsExternal());
     571           6 :     CHECK(!source->IsExternalOneByte());
     572             :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     573           6 :     CHECK(!source->GetExternalStringResourceBase(&encoding));
     574           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     575             :     bool success = source->MakeExternal(new TestResource(two_byte_source,
     576          12 :                                                          &dispose_count));
     577           6 :     CHECK(success);
     578           6 :     Local<Script> script = v8_compile(source);
     579          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     580           6 :     CHECK(value->IsNumber());
     581          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     582           6 :     CcTest::CollectAllGarbage();
     583          12 :     CHECK_EQ(0, dispose_count);
     584             :   }
     585           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     586           6 :   CcTest::CollectAllGarbage();
     587           6 :   CHECK_EQ(1, dispose_count);
     588           6 : }
     589             : 
     590             : 
     591       23724 : THREADED_TEST(ScriptMakingExternalOneByteString) {
     592           6 :   int dispose_count = 0;
     593             :   const char* c_source = "1 + 2 * 3";
     594             :   {
     595           6 :     LocalContext env;
     596          12 :     v8::HandleScope scope(env->GetIsolate());
     597           6 :     Local<String> source = v8_str(c_source);
     598             :     // Trigger GCs so that the newly allocated string moves to old gen.
     599           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     600           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     601             :     bool success = source->MakeExternal(
     602          12 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
     603           6 :     CHECK(success);
     604           6 :     Local<Script> script = v8_compile(source);
     605          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     606           6 :     CHECK(value->IsNumber());
     607          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     608           6 :     CcTest::CollectAllGarbage();
     609          12 :     CHECK_EQ(0, dispose_count);
     610             :   }
     611           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     612           6 :   CcTest::CollectAllGarbage();
     613           6 :   CHECK_EQ(1, dispose_count);
     614           6 : }
     615             : 
     616             : 
     617       23723 : TEST(MakingExternalStringConditions) {
     618           5 :   LocalContext env;
     619          10 :   v8::HandleScope scope(env->GetIsolate());
     620             : 
     621             :   // Free some space in the new space so that we can check freshness.
     622           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     623           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     624             : 
     625           5 :   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
     626             :   Local<String> local_string =
     627             :       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
     628           5 :                              v8::NewStringType::kNormal)
     629           5 :           .ToLocalChecked();
     630             :   i::DeleteArray(two_byte_string);
     631             : 
     632             :   // We should refuse to externalize new space strings.
     633           5 :   CHECK(!local_string->CanMakeExternal());
     634             :   // Trigger GCs so that the newly allocated string moves to old gen.
     635           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     636           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     637             :   // Old space strings should be accepted.
     638          10 :   CHECK(local_string->CanMakeExternal());
     639           5 : }
     640             : 
     641             : 
     642       23723 : TEST(MakingExternalOneByteStringConditions) {
     643           5 :   LocalContext env;
     644          10 :   v8::HandleScope scope(env->GetIsolate());
     645             : 
     646             :   // Free some space in the new space so that we can check freshness.
     647           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     648           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     649             : 
     650           5 :   Local<String> local_string = v8_str("s1");
     651             :   // We should refuse to externalize new space strings.
     652           5 :   CHECK(!local_string->CanMakeExternal());
     653             :   // Trigger GCs so that the newly allocated string moves to old gen.
     654           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     655           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     656             :   // Old space strings should be accepted.
     657          10 :   CHECK(local_string->CanMakeExternal());
     658           5 : }
     659             : 
     660             : 
     661       23723 : TEST(MakingExternalUnalignedOneByteString) {
     662           5 :   LocalContext env;
     663          10 :   v8::HandleScope scope(env->GetIsolate());
     664             : 
     665             :   CompileRun("function cons(a, b) { return a + b; }"
     666             :              "function slice(a) { return a.substring(1); }");
     667             :   // Create a cons string that will land in old pointer space.
     668             :   Local<String> cons = Local<String>::Cast(CompileRun(
     669             :       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
     670             :   // Create a sliced string that will land in old pointer space.
     671             :   Local<String> slice = Local<String>::Cast(CompileRun(
     672             :       "slice('abcdefghijklmnopqrstuvwxyz');"));
     673             : 
     674             :   // Trigger GCs so that the newly allocated string moves to old gen.
     675           5 :   i::heap::SimulateFullSpace(CcTest::heap()->old_space());
     676           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     677           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     678             : 
     679             :   // Turn into external string with unaligned resource data.
     680             :   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
     681             :   bool success = cons->MakeExternal(
     682          10 :       new TestOneByteResource(i::StrDup(c_cons), nullptr, 1));
     683           5 :   CHECK(success);
     684             :   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
     685             :   success = slice->MakeExternal(
     686          10 :       new TestOneByteResource(i::StrDup(c_slice), nullptr, 1));
     687           5 :   CHECK(success);
     688             : 
     689             :   // Trigger GCs and force evacuation.
     690           5 :   CcTest::CollectAllGarbage();
     691          10 :   CcTest::CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
     692           5 : }
     693             : 
     694             : 
     695       23724 : THREADED_TEST(UsingExternalString) {
     696             :   i::Factory* factory = CcTest::i_isolate()->factory();
     697             :   {
     698           6 :     v8::HandleScope scope(CcTest::isolate());
     699           6 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     700             :     Local<String> string =
     701             :         String::NewExternalTwoByte(CcTest::isolate(),
     702          12 :                                    new TestResource(two_byte_string))
     703           6 :             .ToLocalChecked();
     704           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     705             :     // Trigger GCs so that the newly allocated string moves to old gen.
     706           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     707           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     708             :     i::Handle<i::String> isymbol =
     709           6 :         factory->InternalizeString(istring);
     710           6 :     CHECK(isymbol->IsInternalizedString());
     711             :   }
     712           6 :   CcTest::CollectAllGarbage();
     713           6 :   CcTest::CollectAllGarbage();
     714           6 : }
     715             : 
     716             : 
     717       23724 : THREADED_TEST(UsingExternalOneByteString) {
     718             :   i::Factory* factory = CcTest::i_isolate()->factory();
     719             :   {
     720           6 :     v8::HandleScope scope(CcTest::isolate());
     721             :     const char* one_byte_string = "test string";
     722             :     Local<String> string =
     723             :         String::NewExternalOneByte(
     724             :             CcTest::isolate(),
     725          12 :             new TestOneByteResource(i::StrDup(one_byte_string)))
     726           6 :             .ToLocalChecked();
     727           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     728             :     // Trigger GCs so that the newly allocated string moves to old gen.
     729           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     730           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     731             :     i::Handle<i::String> isymbol =
     732           6 :         factory->InternalizeString(istring);
     733           6 :     CHECK(isymbol->IsInternalizedString());
     734             :   }
     735           6 :   CcTest::CollectAllGarbage();
     736           6 :   CcTest::CollectAllGarbage();
     737           6 : }
     738             : 
     739             : 
     740           6 : class RandomLengthResource : public v8::String::ExternalStringResource {
     741             :  public:
     742           6 :   explicit RandomLengthResource(int length) : length_(length) {}
     743           6 :   virtual const uint16_t* data() const { return string_; }
     744           6 :   virtual size_t length() const { return length_; }
     745             : 
     746             :  private:
     747             :   uint16_t string_[10];
     748             :   int length_;
     749             : };
     750             : 
     751             : 
     752          16 : class RandomLengthOneByteResource
     753             :     : public v8::String::ExternalOneByteStringResource {
     754             :  public:
     755          11 :   explicit RandomLengthOneByteResource(int length) : length_(length) {}
     756          16 :   virtual const char* data() const { return string_; }
     757          21 :   virtual size_t length() const { return length_; }
     758             : 
     759             :  private:
     760             :   char string_[10];
     761             :   int length_;
     762             : };
     763             : 
     764             : 
     765       23724 : THREADED_TEST(NewExternalForVeryLongString) {
     766           6 :   auto isolate = CcTest::isolate();
     767             :   {
     768           6 :     v8::HandleScope scope(isolate);
     769          12 :     v8::TryCatch try_catch(isolate);
     770             :     RandomLengthOneByteResource r(1 << 30);
     771             :     v8::MaybeLocal<v8::String> maybe_str =
     772           6 :         v8::String::NewExternalOneByte(isolate, &r);
     773           6 :     CHECK(maybe_str.IsEmpty());
     774          12 :     CHECK(!try_catch.HasCaught());
     775             :   }
     776             : 
     777             :   {
     778           6 :     v8::HandleScope scope(isolate);
     779          12 :     v8::TryCatch try_catch(isolate);
     780             :     RandomLengthResource r(1 << 30);
     781             :     v8::MaybeLocal<v8::String> maybe_str =
     782           6 :         v8::String::NewExternalTwoByte(isolate, &r);
     783           6 :     CHECK(maybe_str.IsEmpty());
     784          12 :     CHECK(!try_catch.HasCaught());
     785             :   }
     786           6 : }
     787             : 
     788             : 
     789       23724 : THREADED_TEST(ScavengeExternalString) {
     790           6 :   i::FLAG_stress_compaction = false;
     791           6 :   i::FLAG_gc_global = false;
     792           6 :   int dispose_count = 0;
     793             :   bool in_new_space = false;
     794             :   {
     795           6 :     v8::HandleScope scope(CcTest::isolate());
     796           6 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     797             :     Local<String> string =
     798             :         String::NewExternalTwoByte(
     799             :             CcTest::isolate(),
     800          12 :             new TestResource(two_byte_string, &dispose_count))
     801           6 :             .ToLocalChecked();
     802             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     803           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
     804           6 :     in_new_space = CcTest::heap()->InNewSpace(*istring);
     805           6 :     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
     806           6 :     CHECK_EQ(0, dispose_count);
     807             :   }
     808           6 :   CcTest::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
     809           6 :   CHECK_EQ(1, dispose_count);
     810           6 : }
     811             : 
     812             : 
     813       23724 : THREADED_TEST(ScavengeExternalOneByteString) {
     814           6 :   i::FLAG_stress_compaction = false;
     815           6 :   i::FLAG_gc_global = false;
     816           6 :   int dispose_count = 0;
     817             :   bool in_new_space = false;
     818             :   {
     819           6 :     v8::HandleScope scope(CcTest::isolate());
     820             :     const char* one_byte_string = "test string";
     821             :     Local<String> string =
     822             :         String::NewExternalOneByte(
     823             :             CcTest::isolate(),
     824          12 :             new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
     825           6 :             .ToLocalChecked();
     826             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     827           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
     828           6 :     in_new_space = CcTest::heap()->InNewSpace(*istring);
     829           6 :     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
     830           6 :     CHECK_EQ(0, dispose_count);
     831             :   }
     832           6 :   CcTest::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
     833           6 :   CHECK_EQ(1, dispose_count);
     834           6 : }
     835             : 
     836             : 
     837          10 : class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
     838             :  public:
     839             :   // Only used by non-threaded tests, so it can use static fields.
     840             :   static int dispose_calls;
     841             :   static int dispose_count;
     842             : 
     843             :   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
     844          10 :       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
     845             : 
     846          10 :   void Dispose() {
     847          10 :     ++dispose_calls;
     848          10 :     if (dispose_) delete this;
     849          10 :   }
     850             :  private:
     851             :   bool dispose_;
     852             : };
     853             : 
     854             : 
     855             : int TestOneByteResourceWithDisposeControl::dispose_count = 0;
     856             : int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     857             : 
     858             : 
     859       23723 : TEST(ExternalStringWithDisposeHandling) {
     860             :   const char* c_source = "1 + 2 * 3";
     861             : 
     862             :   // Use a stack allocated external string resource allocated object.
     863           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     864           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     865           5 :   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
     866             :   {
     867           5 :     LocalContext env;
     868          10 :     v8::HandleScope scope(env->GetIsolate());
     869             :     Local<String> source =
     870           5 :         String::NewExternalOneByte(env->GetIsolate(), &res_stack)
     871          10 :             .ToLocalChecked();
     872           5 :     Local<Script> script = v8_compile(source);
     873          10 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     874           5 :     CHECK(value->IsNumber());
     875          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     876           5 :     CcTest::CollectAllAvailableGarbage();
     877          10 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     878             :   }
     879           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     880           5 :   CcTest::CollectAllAvailableGarbage();
     881           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     882           5 :   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     883             : 
     884             :   // Use a heap allocated external string resource allocated object.
     885           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     886           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     887             :   TestOneByteResource* res_heap =
     888           5 :       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
     889             :   {
     890           5 :     LocalContext env;
     891          10 :     v8::HandleScope scope(env->GetIsolate());
     892             :     Local<String> source =
     893           5 :         String::NewExternalOneByte(env->GetIsolate(), res_heap)
     894          10 :             .ToLocalChecked();
     895           5 :     Local<Script> script = v8_compile(source);
     896          10 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     897           5 :     CHECK(value->IsNumber());
     898          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     899           5 :     CcTest::CollectAllAvailableGarbage();
     900          10 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     901             :   }
     902           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     903           5 :   CcTest::CollectAllAvailableGarbage();
     904           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     905           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
     906           5 : }
     907             : 
     908             : 
     909       23724 : THREADED_TEST(StringConcat) {
     910             :   {
     911           6 :     LocalContext env;
     912          12 :     v8::HandleScope scope(env->GetIsolate());
     913             :     const char* one_byte_string_1 = "function a_times_t";
     914             :     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
     915             :     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
     916             :     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
     917             :     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     918             :     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     919             :     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
     920           6 :     Local<String> left = v8_str(one_byte_string_1);
     921             : 
     922           6 :     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
     923             :     Local<String> right =
     924             :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     925           6 :                                v8::NewStringType::kNormal)
     926          12 :             .ToLocalChecked();
     927             :     i::DeleteArray(two_byte_source);
     928             : 
     929           6 :     Local<String> source = String::Concat(left, right);
     930             :     right = String::NewExternalOneByte(
     931             :                 env->GetIsolate(),
     932          12 :                 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
     933          12 :                 .ToLocalChecked();
     934           6 :     source = String::Concat(source, right);
     935             :     right = String::NewExternalTwoByte(
     936             :                 env->GetIsolate(),
     937          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
     938          12 :                 .ToLocalChecked();
     939           6 :     source = String::Concat(source, right);
     940           6 :     right = v8_str(one_byte_string_2);
     941           6 :     source = String::Concat(source, right);
     942             : 
     943           6 :     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
     944             :     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     945           6 :                                    v8::NewStringType::kNormal)
     946          12 :                 .ToLocalChecked();
     947             :     i::DeleteArray(two_byte_source);
     948             : 
     949           6 :     source = String::Concat(source, right);
     950             :     right = String::NewExternalTwoByte(
     951             :                 env->GetIsolate(),
     952          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
     953          12 :                 .ToLocalChecked();
     954           6 :     source = String::Concat(source, right);
     955           6 :     Local<Script> script = v8_compile(source);
     956          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     957           6 :     CHECK(value->IsNumber());
     958          18 :     CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
     959             :   }
     960           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     961           6 :   CcTest::CollectAllGarbage();
     962           6 :   CcTest::CollectAllGarbage();
     963           6 : }
     964             : 
     965             : 
     966       23724 : THREADED_TEST(GlobalProperties) {
     967           6 :   LocalContext env;
     968          12 :   v8::HandleScope scope(env->GetIsolate());
     969           6 :   v8::Local<v8::Object> global = env->Global();
     970          18 :   CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
     971          18 :   Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
     972          18 :   CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
     973           6 : }
     974             : 
     975             : 
     976        1980 : static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
     977             :                                  i::Address callback) {
     978         660 :   ApiTestFuzzer::Fuzz();
     979         660 :   CheckReturnValue(info, callback);
     980         660 :   info.GetReturnValue().Set(v8_str("bad value"));
     981         660 :   info.GetReturnValue().Set(v8_num(102));
     982         660 : }
     983             : 
     984             : 
     985         330 : static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
     986         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
     987             : }
     988             : 
     989             : 
     990         330 : static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
     991         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
     992             : }
     993             : 
     994          22 : static void construct_callback(
     995         154 :     const v8::FunctionCallbackInfo<Value>& info) {
     996          22 :   ApiTestFuzzer::Fuzz();
     997          22 :   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
     998          88 :   CHECK(
     999             :       info.This()
    1000             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
    1001             :           .FromJust());
    1002          88 :   CHECK(
    1003             :       info.This()
    1004             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
    1005             :           .FromJust());
    1006          22 :   info.GetReturnValue().Set(v8_str("bad value"));
    1007             :   info.GetReturnValue().Set(info.This());
    1008          22 : }
    1009             : 
    1010             : 
    1011         330 : static void Return239Callback(
    1012             :     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    1013         330 :   ApiTestFuzzer::Fuzz();
    1014         330 :   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    1015         330 :   info.GetReturnValue().Set(v8_str("bad value"));
    1016         330 :   info.GetReturnValue().Set(v8_num(239));
    1017         330 : }
    1018             : 
    1019             : 
    1020             : template<typename Handler>
    1021          11 : static void TestFunctionTemplateInitializer(Handler handler,
    1022             :                                             Handler handler_2) {
    1023             :   // Test constructor calls.
    1024             :   {
    1025          11 :     LocalContext env;
    1026          11 :     v8::Isolate* isolate = env->GetIsolate();
    1027          22 :     v8::HandleScope scope(isolate);
    1028             : 
    1029             :     Local<v8::FunctionTemplate> fun_templ =
    1030          11 :         v8::FunctionTemplate::New(isolate, handler);
    1031          22 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1032          55 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1033          11 :     Local<Script> script = v8_compile("obj()");
    1034         341 :     for (int i = 0; i < 30; i++) {
    1035         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1036          11 :     }
    1037             :   }
    1038             :   // Use SetCallHandler to initialize a function template, should work like
    1039             :   // the previous one.
    1040             :   {
    1041          11 :     LocalContext env;
    1042          11 :     v8::Isolate* isolate = env->GetIsolate();
    1043          22 :     v8::HandleScope scope(isolate);
    1044             : 
    1045          11 :     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
    1046          11 :     fun_templ->SetCallHandler(handler_2);
    1047          11 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1048          55 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1049          11 :     Local<Script> script = v8_compile("obj()");
    1050         341 :     for (int i = 0; i < 30; i++) {
    1051         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1052          11 :     }
    1053             :   }
    1054          11 : }
    1055             : 
    1056             : 
    1057             : template<typename Constructor, typename Accessor>
    1058          11 : static void TestFunctionTemplateAccessor(Constructor constructor,
    1059             :                                          Accessor accessor) {
    1060          11 :   LocalContext env;
    1061          22 :   v8::HandleScope scope(env->GetIsolate());
    1062             : 
    1063             :   Local<v8::FunctionTemplate> fun_templ =
    1064          11 :       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
    1065          11 :   fun_templ->SetClassName(v8_str("funky"));
    1066          22 :   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
    1067          11 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1068          55 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1069             :   Local<Value> result =
    1070          33 :       v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
    1071          33 :   CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
    1072             :   CompileRun("var obj_instance = new obj();");
    1073             :   Local<Script> script;
    1074          11 :   script = v8_compile("obj_instance.x");
    1075         341 :   for (int i = 0; i < 30; i++) {
    1076         330 :     CHECK_EQ(1, v8_run_int32value(script));
    1077             :   }
    1078          11 :   script = v8_compile("obj_instance.m");
    1079         341 :   for (int i = 0; i < 30; i++) {
    1080         330 :     CHECK_EQ(239, v8_run_int32value(script));
    1081          11 :   }
    1082          11 : }
    1083             : 
    1084             : 
    1085       47452 : THREADED_PROFILED_TEST(FunctionTemplate) {
    1086          11 :   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
    1087          11 :   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
    1088          11 : }
    1089             : 
    1090             : 
    1091        1980 : static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    1092         660 :   ApiTestFuzzer::Fuzz();
    1093         660 :   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
    1094         660 :   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
    1095         660 : }
    1096             : 
    1097             : 
    1098             : template<typename Callback>
    1099          11 : static void TestSimpleCallback(Callback callback) {
    1100          11 :   LocalContext env;
    1101          11 :   v8::Isolate* isolate = env->GetIsolate();
    1102          22 :   v8::HandleScope scope(isolate);
    1103             : 
    1104             :   v8::Local<v8::ObjectTemplate> object_template =
    1105          11 :       v8::ObjectTemplate::New(isolate);
    1106          22 :   object_template->Set(isolate, "callback",
    1107             :                        v8::FunctionTemplate::New(isolate, callback));
    1108             :   v8::Local<v8::Object> object =
    1109          11 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1110          55 :   CHECK((*env)
    1111             :             ->Global()
    1112             :             ->Set(env.local(), v8_str("callback_object"), object)
    1113             :             .FromJust());
    1114             :   v8::Local<v8::Script> script;
    1115          11 :   script = v8_compile("callback_object.callback(17)");
    1116         341 :   for (int i = 0; i < 30; i++) {
    1117         330 :     CHECK_EQ(51424, v8_run_int32value(script));
    1118             :   }
    1119          11 :   script = v8_compile("callback_object.callback(17, 24)");
    1120         341 :   for (int i = 0; i < 30; i++) {
    1121         330 :     CHECK_EQ(51425, v8_run_int32value(script));
    1122          11 :   }
    1123          11 : }
    1124             : 
    1125             : 
    1126       47452 : THREADED_PROFILED_TEST(SimpleCallback) {
    1127          11 :   TestSimpleCallback(SimpleCallback);
    1128          11 : }
    1129             : 
    1130             : 
    1131             : template<typename T>
    1132             : void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
    1133             : 
    1134             : // constant return values
    1135             : static int32_t fast_return_value_int32 = 471;
    1136             : static uint32_t fast_return_value_uint32 = 571;
    1137             : static const double kFastReturnValueDouble = 2.7;
    1138             : // variable return values
    1139             : static bool fast_return_value_bool = false;
    1140             : enum ReturnValueOddball {
    1141             :   kNullReturnValue,
    1142             :   kUndefinedReturnValue,
    1143             :   kEmptyStringReturnValue
    1144             : };
    1145             : static ReturnValueOddball fast_return_value_void;
    1146             : static bool fast_return_value_object_is_empty = false;
    1147             : 
    1148             : // Helper function to avoid compiler error: insufficient contextual information
    1149             : // to determine type when applying FUNCTION_ADDR to a template function.
    1150             : static i::Address address_of(v8::FunctionCallback callback) {
    1151             :   return FUNCTION_ADDR(callback);
    1152             : }
    1153             : 
    1154             : template<>
    1155         165 : void FastReturnValueCallback<int32_t>(
    1156         165 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1157         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
    1158         165 :   info.GetReturnValue().Set(fast_return_value_int32);
    1159         165 : }
    1160             : 
    1161             : template<>
    1162         165 : void FastReturnValueCallback<uint32_t>(
    1163         165 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1164         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
    1165         165 :   info.GetReturnValue().Set(fast_return_value_uint32);
    1166         165 : }
    1167             : 
    1168             : template<>
    1169          11 : void FastReturnValueCallback<double>(
    1170          11 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1171          11 :   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
    1172             :   info.GetReturnValue().Set(kFastReturnValueDouble);
    1173          11 : }
    1174             : 
    1175             : template<>
    1176          22 : void FastReturnValueCallback<bool>(
    1177          22 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1178          22 :   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
    1179          22 :   info.GetReturnValue().Set(fast_return_value_bool);
    1180          22 : }
    1181             : 
    1182             : template<>
    1183          33 : void FastReturnValueCallback<void>(
    1184          33 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1185          33 :   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
    1186          33 :   switch (fast_return_value_void) {
    1187             :     case kNullReturnValue:
    1188             :       info.GetReturnValue().SetNull();
    1189          11 :       break;
    1190             :     case kUndefinedReturnValue:
    1191             :       info.GetReturnValue().SetUndefined();
    1192          11 :       break;
    1193             :     case kEmptyStringReturnValue:
    1194             :       info.GetReturnValue().SetEmptyString();
    1195          11 :       break;
    1196             :   }
    1197          33 : }
    1198             : 
    1199             : template<>
    1200          22 : void FastReturnValueCallback<Object>(
    1201          33 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1202             :   v8::Local<v8::Object> object;
    1203          22 :   if (!fast_return_value_object_is_empty) {
    1204          11 :     object = Object::New(info.GetIsolate());
    1205             :   }
    1206             :   info.GetReturnValue().Set(object);
    1207          22 : }
    1208             : 
    1209             : template <typename T>
    1210         418 : Local<Value> TestFastReturnValues() {
    1211         418 :   LocalContext env;
    1212         418 :   v8::Isolate* isolate = env->GetIsolate();
    1213         418 :   v8::EscapableHandleScope scope(isolate);
    1214             :   v8::Local<v8::ObjectTemplate> object_template =
    1215         418 :       v8::ObjectTemplate::New(isolate);
    1216             :   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
    1217             :   object_template->Set(isolate, "callback",
    1218         836 :                        v8::FunctionTemplate::New(isolate, callback));
    1219             :   v8::Local<v8::Object> object =
    1220         418 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1221        2090 :   CHECK((*env)
    1222             :             ->Global()
    1223             :             ->Set(env.local(), v8_str("callback_object"), object)
    1224             :             .FromJust());
    1225         418 :   return scope.Escape(CompileRun("callback_object.callback()"));
    1226             : }
    1227             : 
    1228             : 
    1229       47452 : THREADED_PROFILED_TEST(FastReturnValues) {
    1230          11 :   LocalContext env;
    1231          11 :   v8::Isolate* isolate = env->GetIsolate();
    1232          22 :   v8::HandleScope scope(isolate);
    1233             :   v8::Local<v8::Value> value;
    1234             :   // check int32_t and uint32_t
    1235             :   int32_t int_values[] = {
    1236             :       0, 234, -723,
    1237             :       i::Smi::kMinValue, i::Smi::kMaxValue
    1238          11 :   };
    1239          66 :   for (size_t i = 0; i < arraysize(int_values); i++) {
    1240         165 :     for (int modifier = -1; modifier <= 1; modifier++) {
    1241         165 :       int int_value = int_values[i] + modifier;
    1242             :       // check int32_t
    1243         165 :       fast_return_value_int32 = int_value;
    1244         165 :       value = TestFastReturnValues<int32_t>();
    1245         165 :       CHECK(value->IsInt32());
    1246         330 :       CHECK_EQ(fast_return_value_int32,
    1247             :                value->Int32Value(env.local()).FromJust());
    1248             :       // check uint32_t
    1249         165 :       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
    1250         165 :       value = TestFastReturnValues<uint32_t>();
    1251         165 :       CHECK(value->IsUint32());
    1252         330 :       CHECK_EQ(fast_return_value_uint32,
    1253             :                value->Uint32Value(env.local()).FromJust());
    1254             :     }
    1255             :   }
    1256             :   // check double
    1257          11 :   value = TestFastReturnValues<double>();
    1258          11 :   CHECK(value->IsNumber());
    1259          22 :   CHECK_EQ(kFastReturnValueDouble,
    1260             :            value->ToNumber(env.local()).ToLocalChecked()->Value());
    1261             :   // check bool values
    1262          22 :   for (int i = 0; i < 2; i++) {
    1263          22 :     fast_return_value_bool = i == 0;
    1264          22 :     value = TestFastReturnValues<bool>();
    1265          22 :     CHECK(value->IsBoolean());
    1266          44 :     CHECK_EQ(fast_return_value_bool,
    1267             :              value->ToBoolean(env.local()).ToLocalChecked()->Value());
    1268             :   }
    1269             :   // check oddballs
    1270             :   ReturnValueOddball oddballs[] = {
    1271             :       kNullReturnValue,
    1272             :       kUndefinedReturnValue,
    1273             :       kEmptyStringReturnValue
    1274          11 :   };
    1275          44 :   for (size_t i = 0; i < arraysize(oddballs); i++) {
    1276          33 :     fast_return_value_void = oddballs[i];
    1277          33 :     value = TestFastReturnValues<void>();
    1278          33 :     switch (fast_return_value_void) {
    1279             :       case kNullReturnValue:
    1280          11 :         CHECK(value->IsNull());
    1281             :         break;
    1282             :       case kUndefinedReturnValue:
    1283          11 :         CHECK(value->IsUndefined());
    1284             :         break;
    1285             :       case kEmptyStringReturnValue:
    1286          11 :         CHECK(value->IsString());
    1287          11 :         CHECK_EQ(0, v8::String::Cast(*value)->Length());
    1288             :         break;
    1289             :     }
    1290             :   }
    1291             :   // check handles
    1292          11 :   fast_return_value_object_is_empty = false;
    1293          11 :   value = TestFastReturnValues<Object>();
    1294          11 :   CHECK(value->IsObject());
    1295          11 :   fast_return_value_object_is_empty = true;
    1296          11 :   value = TestFastReturnValues<Object>();
    1297          22 :   CHECK(value->IsUndefined());
    1298          11 : }
    1299             : 
    1300             : 
    1301       23724 : THREADED_TEST(FunctionTemplateSetLength) {
    1302           6 :   LocalContext env;
    1303           6 :   v8::Isolate* isolate = env->GetIsolate();
    1304          12 :   v8::HandleScope scope(isolate);
    1305             :   {
    1306             :     Local<v8::FunctionTemplate> fun_templ =
    1307             :         v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
    1308           6 :                                   Local<v8::Signature>(), 23);
    1309          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1310          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1311           6 :     Local<Script> script = v8_compile("obj.length");
    1312           6 :     CHECK_EQ(23, v8_run_int32value(script));
    1313             :   }
    1314             :   {
    1315             :     Local<v8::FunctionTemplate> fun_templ =
    1316           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1317           6 :     fun_templ->SetLength(22);
    1318           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1319          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1320           6 :     Local<Script> script = v8_compile("obj.length");
    1321           6 :     CHECK_EQ(22, v8_run_int32value(script));
    1322             :   }
    1323             :   {
    1324             :     // Without setting length it defaults to 0.
    1325             :     Local<v8::FunctionTemplate> fun_templ =
    1326           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1327          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1328          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1329           6 :     Local<Script> script = v8_compile("obj.length");
    1330           6 :     CHECK_EQ(0, v8_run_int32value(script));
    1331           6 :   }
    1332           6 : }
    1333             : 
    1334             : 
    1335             : static void* expected_ptr;
    1336       16848 : static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1337        8424 :   void* ptr = v8::External::Cast(*args.Data())->Value();
    1338        8424 :   CHECK_EQ(expected_ptr, ptr);
    1339             :   args.GetReturnValue().Set(true);
    1340        8424 : }
    1341             : 
    1342             : 
    1343         648 : static void TestExternalPointerWrapping() {
    1344         648 :   LocalContext env;
    1345         648 :   v8::Isolate* isolate = env->GetIsolate();
    1346        1296 :   v8::HandleScope scope(isolate);
    1347             : 
    1348         648 :   v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
    1349             : 
    1350         648 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    1351        4536 :   CHECK(obj->Set(env.local(), v8_str("func"),
    1352             :                  v8::FunctionTemplate::New(isolate, callback, data)
    1353             :                      ->GetFunction(env.local())
    1354             :                      .ToLocalChecked())
    1355             :             .FromJust());
    1356        3240 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
    1357             : 
    1358        1944 :   CHECK(CompileRun("function foo() {\n"
    1359             :                    "  for (var i = 0; i < 13; i++) obj.func();\n"
    1360             :                    "}\n"
    1361             :                    "foo(), true")
    1362             :             ->BooleanValue(env.local())
    1363         648 :             .FromJust());
    1364         648 : }
    1365             : 
    1366             : 
    1367       23724 : THREADED_TEST(ExternalWrap) {
    1368             :   // Check heap allocated object.
    1369           6 :   int* ptr = new int;
    1370           6 :   expected_ptr = ptr;
    1371           6 :   TestExternalPointerWrapping();
    1372           6 :   delete ptr;
    1373             : 
    1374             :   // Check stack allocated object.
    1375             :   int foo;
    1376           6 :   expected_ptr = &foo;
    1377           6 :   TestExternalPointerWrapping();
    1378             : 
    1379             :   // Check not aligned addresses.
    1380             :   const int n = 100;
    1381           6 :   char* s = new char[n];
    1382         606 :   for (int i = 0; i < n; i++) {
    1383         600 :     expected_ptr = s + i;
    1384         600 :     TestExternalPointerWrapping();
    1385             :   }
    1386             : 
    1387           6 :   delete[] s;
    1388             : 
    1389             :   // Check several invalid addresses.
    1390           6 :   expected_ptr = reinterpret_cast<void*>(1);
    1391           6 :   TestExternalPointerWrapping();
    1392             : 
    1393           6 :   expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
    1394           6 :   TestExternalPointerWrapping();
    1395             : 
    1396           6 :   expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
    1397           6 :   TestExternalPointerWrapping();
    1398             : 
    1399             : #if defined(V8_HOST_ARCH_X64)
    1400             :   // Check a value with a leading 1 bit in x64 Smi encoding.
    1401           6 :   expected_ptr = reinterpret_cast<void*>(0x400000000);
    1402           6 :   TestExternalPointerWrapping();
    1403             : 
    1404           6 :   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
    1405           6 :   TestExternalPointerWrapping();
    1406             : 
    1407           6 :   expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
    1408           6 :   TestExternalPointerWrapping();
    1409             : #endif
    1410           6 : }
    1411             : 
    1412             : 
    1413       23724 : THREADED_TEST(FindInstanceInPrototypeChain) {
    1414           6 :   LocalContext env;
    1415           6 :   v8::Isolate* isolate = env->GetIsolate();
    1416          12 :   v8::HandleScope scope(isolate);
    1417             : 
    1418           6 :   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
    1419           6 :   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
    1420           6 :   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
    1421           6 :   derived->Inherit(base);
    1422             : 
    1423             :   Local<v8::Function> base_function =
    1424          12 :       base->GetFunction(env.local()).ToLocalChecked();
    1425             :   Local<v8::Function> derived_function =
    1426           6 :       derived->GetFunction(env.local()).ToLocalChecked();
    1427             :   Local<v8::Function> other_function =
    1428          12 :       other->GetFunction(env.local()).ToLocalChecked();
    1429             : 
    1430             :   Local<v8::Object> base_instance =
    1431           6 :       base_function->NewInstance(env.local()).ToLocalChecked();
    1432             :   Local<v8::Object> derived_instance =
    1433           6 :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1434             :   Local<v8::Object> derived_instance2 =
    1435           6 :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1436             :   Local<v8::Object> other_instance =
    1437           6 :       other_function->NewInstance(env.local()).ToLocalChecked();
    1438          18 :   CHECK(
    1439             :       derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
    1440             :           .FromJust());
    1441          18 :   CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
    1442             :             .FromJust());
    1443             : 
    1444             :   // base_instance is only an instance of base.
    1445          18 :   CHECK(base_instance->Equals(env.local(),
    1446             :                               base_instance->FindInstanceInPrototypeChain(base))
    1447             :             .FromJust());
    1448          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
    1449          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1450             : 
    1451             :   // derived_instance is an instance of base and derived.
    1452          18 :   CHECK(derived_instance->Equals(env.local(),
    1453             :                                  derived_instance->FindInstanceInPrototypeChain(
    1454             :                                      base))
    1455             :             .FromJust());
    1456          18 :   CHECK(derived_instance->Equals(env.local(),
    1457             :                                  derived_instance->FindInstanceInPrototypeChain(
    1458             :                                      derived))
    1459             :             .FromJust());
    1460          12 :   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1461             : 
    1462             :   // other_instance is an instance of other and its immediate
    1463             :   // prototype derived_instance2 is an instance of base and derived.
    1464             :   // Note, derived_instance is an instance of base and derived too,
    1465             :   // but it comes after derived_instance2 in the prototype chain of
    1466             :   // other_instance.
    1467          18 :   CHECK(derived_instance2->Equals(
    1468             :                              env.local(),
    1469             :                              other_instance->FindInstanceInPrototypeChain(base))
    1470             :             .FromJust());
    1471          18 :   CHECK(derived_instance2->Equals(env.local(),
    1472             :                                   other_instance->FindInstanceInPrototypeChain(
    1473             :                                       derived))
    1474             :             .FromJust());
    1475          18 :   CHECK(other_instance->Equals(
    1476             :                           env.local(),
    1477             :                           other_instance->FindInstanceInPrototypeChain(other))
    1478           6 :             .FromJust());
    1479           6 : }
    1480             : 
    1481             : 
    1482       23724 : THREADED_TEST(TinyInteger) {
    1483           6 :   LocalContext env;
    1484           6 :   v8::Isolate* isolate = env->GetIsolate();
    1485          12 :   v8::HandleScope scope(isolate);
    1486             : 
    1487             :   int32_t value = 239;
    1488           6 :   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1489           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1490             : 
    1491           6 :   value_obj = v8::Integer::New(isolate, value);
    1492          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1493           6 : }
    1494             : 
    1495             : 
    1496       23724 : THREADED_TEST(BigSmiInteger) {
    1497           6 :   LocalContext env;
    1498          12 :   v8::HandleScope scope(env->GetIsolate());
    1499           6 :   v8::Isolate* isolate = CcTest::isolate();
    1500             : 
    1501             :   int32_t value = i::Smi::kMaxValue;
    1502             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1503             :   if (i::SmiValuesAre31Bits()) {
    1504             :     CHECK(i::Smi::IsValid(value));
    1505             :     CHECK(!i::Smi::IsValid(value + 1));
    1506             : 
    1507             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1508             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1509             : 
    1510             :     value_obj = v8::Integer::New(isolate, value);
    1511             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1512           6 :   }
    1513           6 : }
    1514             : 
    1515             : 
    1516       23724 : THREADED_TEST(BigInteger) {
    1517           6 :   LocalContext env;
    1518          12 :   v8::HandleScope scope(env->GetIsolate());
    1519           6 :   v8::Isolate* isolate = CcTest::isolate();
    1520             : 
    1521             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1522             :   if (i::SmiValuesAre31Bits()) {
    1523             :     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
    1524             :     // The code will not be run in that case, due to the "if" guard.
    1525             :     int32_t value =
    1526             :         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
    1527             :     CHECK_GT(value, i::Smi::kMaxValue);
    1528             :     CHECK(!i::Smi::IsValid(value));
    1529             : 
    1530             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1531             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1532             : 
    1533             :     value_obj = v8::Integer::New(isolate, value);
    1534             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1535           6 :   }
    1536           6 : }
    1537             : 
    1538             : 
    1539       23724 : THREADED_TEST(TinyUnsignedInteger) {
    1540           6 :   LocalContext env;
    1541          12 :   v8::HandleScope scope(env->GetIsolate());
    1542           6 :   v8::Isolate* isolate = CcTest::isolate();
    1543             : 
    1544             :   uint32_t value = 239;
    1545             : 
    1546           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1547           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1548             : 
    1549           6 :   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1550          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1551           6 : }
    1552             : 
    1553             : 
    1554       23724 : THREADED_TEST(BigUnsignedSmiInteger) {
    1555           6 :   LocalContext env;
    1556          12 :   v8::HandleScope scope(env->GetIsolate());
    1557           6 :   v8::Isolate* isolate = CcTest::isolate();
    1558             : 
    1559             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
    1560             :   CHECK(i::Smi::IsValid(value));
    1561             :   CHECK(!i::Smi::IsValid(value + 1));
    1562             : 
    1563           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1564           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1565             : 
    1566           6 :   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1567          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1568           6 : }
    1569             : 
    1570             : 
    1571       23724 : THREADED_TEST(BigUnsignedInteger) {
    1572           6 :   LocalContext env;
    1573          12 :   v8::HandleScope scope(env->GetIsolate());
    1574           6 :   v8::Isolate* isolate = CcTest::isolate();
    1575             : 
    1576             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
    1577             :   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
    1578             :   CHECK(!i::Smi::IsValid(value));
    1579             : 
    1580           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1581           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1582             : 
    1583           6 :   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1584          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1585           6 : }
    1586             : 
    1587             : 
    1588       23724 : THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
    1589           6 :   LocalContext env;
    1590          12 :   v8::HandleScope scope(env->GetIsolate());
    1591           6 :   v8::Isolate* isolate = CcTest::isolate();
    1592             : 
    1593             :   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
    1594             :   uint32_t value = INT32_MAX_AS_UINT + 1;
    1595             :   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
    1596             : 
    1597           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1598           6 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1599             : 
    1600           6 :   value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1601          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1602           6 : }
    1603             : 
    1604             : 
    1605       23724 : THREADED_TEST(IsNativeError) {
    1606           6 :   LocalContext env;
    1607          12 :   v8::HandleScope scope(env->GetIsolate());
    1608             :   v8::Local<Value> syntax_error = CompileRun(
    1609             :       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
    1610           6 :   CHECK(syntax_error->IsNativeError());
    1611             :   v8::Local<Value> not_error = CompileRun("{a:42}");
    1612           6 :   CHECK(!not_error->IsNativeError());
    1613             :   v8::Local<Value> not_object = CompileRun("42");
    1614          12 :   CHECK(!not_object->IsNativeError());
    1615           6 : }
    1616             : 
    1617             : 
    1618       23724 : THREADED_TEST(IsGeneratorFunctionOrObject) {
    1619           6 :   LocalContext env;
    1620          12 :   v8::HandleScope scope(env->GetIsolate());
    1621             : 
    1622             :   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
    1623             :   v8::Local<Value> gen = CompileRun("gen");
    1624             :   v8::Local<Value> genObj = CompileRun("gen()");
    1625             :   v8::Local<Value> object = CompileRun("{a:42}");
    1626             :   v8::Local<Value> func = CompileRun("func");
    1627             : 
    1628           6 :   CHECK(gen->IsGeneratorFunction());
    1629           6 :   CHECK(gen->IsFunction());
    1630           6 :   CHECK(!gen->IsGeneratorObject());
    1631             : 
    1632           6 :   CHECK(!genObj->IsGeneratorFunction());
    1633           6 :   CHECK(!genObj->IsFunction());
    1634           6 :   CHECK(genObj->IsGeneratorObject());
    1635             : 
    1636           6 :   CHECK(!object->IsGeneratorFunction());
    1637           6 :   CHECK(!object->IsFunction());
    1638           6 :   CHECK(!object->IsGeneratorObject());
    1639             : 
    1640           6 :   CHECK(!func->IsGeneratorFunction());
    1641           6 :   CHECK(func->IsFunction());
    1642          12 :   CHECK(!func->IsGeneratorObject());
    1643           6 : }
    1644             : 
    1645       23724 : THREADED_TEST(IsAsyncFunction) {
    1646           6 :   LocalContext env;
    1647           6 :   v8::Isolate* isolate = env->GetIsolate();
    1648          12 :   v8::HandleScope scope(isolate);
    1649             : 
    1650             :   CompileRun("async function foo() {}");
    1651             :   v8::Local<Value> foo = CompileRun("foo");
    1652             : 
    1653           6 :   CHECK(foo->IsAsyncFunction());
    1654           6 :   CHECK(foo->IsFunction());
    1655           6 :   CHECK(!foo->IsGeneratorFunction());
    1656           6 :   CHECK(!foo->IsGeneratorObject());
    1657             : 
    1658             :   CompileRun("function bar() {}");
    1659             :   v8::Local<Value> bar = CompileRun("bar");
    1660             : 
    1661           6 :   CHECK(!bar->IsAsyncFunction());
    1662          12 :   CHECK(bar->IsFunction());
    1663           6 : }
    1664             : 
    1665       23724 : THREADED_TEST(ArgumentsObject) {
    1666           6 :   LocalContext env;
    1667          12 :   v8::HandleScope scope(env->GetIsolate());
    1668             :   v8::Local<Value> arguments_object =
    1669             :       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
    1670           6 :   CHECK(arguments_object->IsArgumentsObject());
    1671             :   v8::Local<Value> array = CompileRun("[1,2,3]");
    1672           6 :   CHECK(!array->IsArgumentsObject());
    1673             :   v8::Local<Value> object = CompileRun("{a:42}");
    1674          12 :   CHECK(!object->IsArgumentsObject());
    1675           6 : }
    1676             : 
    1677             : 
    1678       23724 : THREADED_TEST(IsMapOrSet) {
    1679           6 :   LocalContext env;
    1680          12 :   v8::HandleScope scope(env->GetIsolate());
    1681             :   v8::Local<Value> map = CompileRun("new Map()");
    1682             :   v8::Local<Value> set = CompileRun("new Set()");
    1683             :   v8::Local<Value> weak_map = CompileRun("new WeakMap()");
    1684             :   v8::Local<Value> weak_set = CompileRun("new WeakSet()");
    1685           6 :   CHECK(map->IsMap());
    1686           6 :   CHECK(set->IsSet());
    1687           6 :   CHECK(weak_map->IsWeakMap());
    1688           6 :   CHECK(weak_set->IsWeakSet());
    1689             : 
    1690           6 :   CHECK(!map->IsSet());
    1691           6 :   CHECK(!map->IsWeakMap());
    1692           6 :   CHECK(!map->IsWeakSet());
    1693             : 
    1694           6 :   CHECK(!set->IsMap());
    1695           6 :   CHECK(!set->IsWeakMap());
    1696           6 :   CHECK(!set->IsWeakSet());
    1697             : 
    1698           6 :   CHECK(!weak_map->IsMap());
    1699           6 :   CHECK(!weak_map->IsSet());
    1700           6 :   CHECK(!weak_map->IsWeakSet());
    1701             : 
    1702           6 :   CHECK(!weak_set->IsMap());
    1703           6 :   CHECK(!weak_set->IsSet());
    1704           6 :   CHECK(!weak_set->IsWeakMap());
    1705             : 
    1706             :   v8::Local<Value> object = CompileRun("{a:42}");
    1707           6 :   CHECK(!object->IsMap());
    1708           6 :   CHECK(!object->IsSet());
    1709           6 :   CHECK(!object->IsWeakMap());
    1710          12 :   CHECK(!object->IsWeakSet());
    1711           6 : }
    1712             : 
    1713             : 
    1714       23724 : THREADED_TEST(StringObject) {
    1715           6 :   LocalContext env;
    1716          12 :   v8::HandleScope scope(env->GetIsolate());
    1717             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1718           6 :   CHECK(boxed_string->IsStringObject());
    1719             :   v8::Local<Value> unboxed_string = CompileRun("\"test\"");
    1720           6 :   CHECK(!unboxed_string->IsStringObject());
    1721             :   v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
    1722           6 :   CHECK(!boxed_not_string->IsStringObject());
    1723             :   v8::Local<Value> not_object = CompileRun("0");
    1724           6 :   CHECK(!not_object->IsStringObject());
    1725             :   v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
    1726           6 :   CHECK(!as_boxed.IsEmpty());
    1727           6 :   Local<v8::String> the_string = as_boxed->ValueOf();
    1728           6 :   CHECK(!the_string.IsEmpty());
    1729           6 :   ExpectObject("\"test\"", the_string);
    1730           6 :   v8::Local<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
    1731           6 :   CHECK(new_boxed_string->IsStringObject());
    1732             :   as_boxed = new_boxed_string.As<v8::StringObject>();
    1733           6 :   the_string = as_boxed->ValueOf();
    1734           6 :   CHECK(!the_string.IsEmpty());
    1735          12 :   ExpectObject("\"test\"", the_string);
    1736           6 : }
    1737             : 
    1738             : 
    1739       23723 : TEST(StringObjectDelete) {
    1740           5 :   LocalContext context;
    1741          10 :   v8::HandleScope scope(context->GetIsolate());
    1742             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1743           5 :   CHECK(boxed_string->IsStringObject());
    1744             :   v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
    1745          10 :   CHECK(!str_obj->Delete(context.local(), 2).FromJust());
    1746          15 :   CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
    1747           5 : }
    1748             : 
    1749             : 
    1750       23724 : THREADED_TEST(NumberObject) {
    1751           6 :   LocalContext env;
    1752          12 :   v8::HandleScope scope(env->GetIsolate());
    1753             :   v8::Local<Value> boxed_number = CompileRun("new Number(42)");
    1754           6 :   CHECK(boxed_number->IsNumberObject());
    1755             :   v8::Local<Value> unboxed_number = CompileRun("42");
    1756           6 :   CHECK(!unboxed_number->IsNumberObject());
    1757             :   v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
    1758           6 :   CHECK(!boxed_not_number->IsNumberObject());
    1759             :   v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
    1760           6 :   CHECK(!as_boxed.IsEmpty());
    1761           6 :   double the_number = as_boxed->ValueOf();
    1762           6 :   CHECK_EQ(42.0, the_number);
    1763             :   v8::Local<v8::Value> new_boxed_number =
    1764           6 :       v8::NumberObject::New(env->GetIsolate(), 43);
    1765           6 :   CHECK(new_boxed_number->IsNumberObject());
    1766             :   as_boxed = new_boxed_number.As<v8::NumberObject>();
    1767           6 :   the_number = as_boxed->ValueOf();
    1768          12 :   CHECK_EQ(43.0, the_number);
    1769           6 : }
    1770             : 
    1771             : 
    1772       23724 : THREADED_TEST(BooleanObject) {
    1773           6 :   LocalContext env;
    1774          12 :   v8::HandleScope scope(env->GetIsolate());
    1775             :   v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
    1776           6 :   CHECK(boxed_boolean->IsBooleanObject());
    1777             :   v8::Local<Value> unboxed_boolean = CompileRun("true");
    1778           6 :   CHECK(!unboxed_boolean->IsBooleanObject());
    1779             :   v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
    1780           6 :   CHECK(!boxed_not_boolean->IsBooleanObject());
    1781             :   v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
    1782           6 :   CHECK(!as_boxed.IsEmpty());
    1783           6 :   bool the_boolean = as_boxed->ValueOf();
    1784           6 :   CHECK(the_boolean);
    1785             :   v8::Local<v8::Value> boxed_true =
    1786           6 :       v8::BooleanObject::New(env->GetIsolate(), true);
    1787             :   v8::Local<v8::Value> boxed_false =
    1788           6 :       v8::BooleanObject::New(env->GetIsolate(), false);
    1789           6 :   CHECK(boxed_true->IsBooleanObject());
    1790           6 :   CHECK(boxed_false->IsBooleanObject());
    1791             :   as_boxed = boxed_true.As<v8::BooleanObject>();
    1792           6 :   CHECK(as_boxed->ValueOf());
    1793             :   as_boxed = boxed_false.As<v8::BooleanObject>();
    1794          12 :   CHECK(!as_boxed->ValueOf());
    1795           6 : }
    1796             : 
    1797             : 
    1798       23724 : THREADED_TEST(PrimitiveAndWrappedBooleans) {
    1799           6 :   LocalContext env;
    1800          12 :   v8::HandleScope scope(env->GetIsolate());
    1801             : 
    1802           6 :   Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
    1803           6 :   CHECK(primitive_false->IsBoolean());
    1804           6 :   CHECK(!primitive_false->IsBooleanObject());
    1805          12 :   CHECK(!primitive_false->BooleanValue(env.local()).FromJust());
    1806           6 :   CHECK(!primitive_false->IsTrue());
    1807           6 :   CHECK(primitive_false->IsFalse());
    1808             : 
    1809           6 :   Local<Value> false_value = BooleanObject::New(env->GetIsolate(), false);
    1810           6 :   CHECK(!false_value->IsBoolean());
    1811           6 :   CHECK(false_value->IsBooleanObject());
    1812          12 :   CHECK(false_value->BooleanValue(env.local()).FromJust());
    1813           6 :   CHECK(!false_value->IsTrue());
    1814           6 :   CHECK(!false_value->IsFalse());
    1815             : 
    1816             :   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
    1817           6 :   CHECK(!false_boolean_object->IsBoolean());
    1818           6 :   CHECK(false_boolean_object->IsBooleanObject());
    1819          12 :   CHECK(false_boolean_object->BooleanValue(env.local()).FromJust());
    1820           6 :   CHECK(!false_boolean_object->ValueOf());
    1821           6 :   CHECK(!false_boolean_object->IsTrue());
    1822           6 :   CHECK(!false_boolean_object->IsFalse());
    1823             : 
    1824           6 :   Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
    1825           6 :   CHECK(primitive_true->IsBoolean());
    1826           6 :   CHECK(!primitive_true->IsBooleanObject());
    1827          12 :   CHECK(primitive_true->BooleanValue(env.local()).FromJust());
    1828           6 :   CHECK(primitive_true->IsTrue());
    1829           6 :   CHECK(!primitive_true->IsFalse());
    1830             : 
    1831           6 :   Local<Value> true_value = BooleanObject::New(env->GetIsolate(), true);
    1832           6 :   CHECK(!true_value->IsBoolean());
    1833           6 :   CHECK(true_value->IsBooleanObject());
    1834          12 :   CHECK(true_value->BooleanValue(env.local()).FromJust());
    1835           6 :   CHECK(!true_value->IsTrue());
    1836           6 :   CHECK(!true_value->IsFalse());
    1837             : 
    1838             :   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
    1839           6 :   CHECK(!true_boolean_object->IsBoolean());
    1840           6 :   CHECK(true_boolean_object->IsBooleanObject());
    1841          12 :   CHECK(true_boolean_object->BooleanValue(env.local()).FromJust());
    1842           6 :   CHECK(true_boolean_object->ValueOf());
    1843           6 :   CHECK(!true_boolean_object->IsTrue());
    1844          12 :   CHECK(!true_boolean_object->IsFalse());
    1845           6 : }
    1846             : 
    1847             : 
    1848       23724 : THREADED_TEST(Number) {
    1849           6 :   LocalContext env;
    1850          12 :   v8::HandleScope scope(env->GetIsolate());
    1851             :   double PI = 3.1415926;
    1852           6 :   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
    1853          24 :   CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
    1854           6 : }
    1855             : 
    1856             : 
    1857       23724 : THREADED_TEST(ToNumber) {
    1858           6 :   LocalContext env;
    1859           6 :   v8::Isolate* isolate = CcTest::isolate();
    1860          12 :   v8::HandleScope scope(isolate);
    1861           6 :   Local<String> str = v8_str("3.1415926");
    1862          18 :   CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
    1863             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1864          12 :   CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
    1865             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1866          18 :   CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
    1867           6 : }
    1868             : 
    1869             : 
    1870       23724 : THREADED_TEST(Date) {
    1871           6 :   LocalContext env;
    1872          12 :   v8::HandleScope scope(env->GetIsolate());
    1873             :   double PI = 3.1415926;
    1874           6 :   Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
    1875          12 :   CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
    1876          24 :   CHECK(date.As<v8::Date>()
    1877             :             ->Set(env.local(), v8_str("property"),
    1878             :                   v8::Integer::New(env->GetIsolate(), 42))
    1879             :             .FromJust());
    1880          24 :   CHECK_EQ(42, date.As<v8::Date>()
    1881             :                    ->Get(env.local(), v8_str("property"))
    1882             :                    .ToLocalChecked()
    1883             :                    ->Int32Value(env.local())
    1884           6 :                    .FromJust());
    1885           6 : }
    1886             : 
    1887             : 
    1888       23724 : THREADED_TEST(Boolean) {
    1889           6 :   LocalContext env;
    1890           6 :   v8::Isolate* isolate = env->GetIsolate();
    1891          12 :   v8::HandleScope scope(isolate);
    1892             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1893           6 :   CHECK(t->Value());
    1894             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1895           6 :   CHECK(!f->Value());
    1896             :   v8::Local<v8::Primitive> u = v8::Undefined(isolate);
    1897          12 :   CHECK(!u->BooleanValue(env.local()).FromJust());
    1898             :   v8::Local<v8::Primitive> n = v8::Null(isolate);
    1899          12 :   CHECK(!n->BooleanValue(env.local()).FromJust());
    1900           6 :   v8::Local<String> str1 = v8_str("");
    1901          18 :   CHECK(!str1->BooleanValue(env.local()).FromJust());
    1902           6 :   v8::Local<String> str2 = v8_str("x");
    1903          18 :   CHECK(str2->BooleanValue(env.local()).FromJust());
    1904          18 :   CHECK(!v8::Number::New(isolate, 0)->BooleanValue(env.local()).FromJust());
    1905          18 :   CHECK(v8::Number::New(isolate, -1)->BooleanValue(env.local()).FromJust());
    1906          18 :   CHECK(v8::Number::New(isolate, 1)->BooleanValue(env.local()).FromJust());
    1907          18 :   CHECK(v8::Number::New(isolate, 42)->BooleanValue(env.local()).FromJust());
    1908          24 :   CHECK(!v8_compile("NaN")
    1909             :              ->Run(env.local())
    1910             :              .ToLocalChecked()
    1911             :              ->BooleanValue(env.local())
    1912           6 :              .FromJust());
    1913           6 : }
    1914             : 
    1915             : 
    1916          12 : static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1917           6 :   ApiTestFuzzer::Fuzz();
    1918           6 :   args.GetReturnValue().Set(v8_num(13.4));
    1919           6 : }
    1920             : 
    1921             : 
    1922           6 : static void GetM(Local<String> name,
    1923             :                  const v8::PropertyCallbackInfo<v8::Value>& info) {
    1924           6 :   ApiTestFuzzer::Fuzz();
    1925           6 :   info.GetReturnValue().Set(v8_num(876));
    1926           6 : }
    1927             : 
    1928             : 
    1929       23724 : THREADED_TEST(GlobalPrototype) {
    1930           6 :   v8::Isolate* isolate = CcTest::isolate();
    1931           6 :   v8::HandleScope scope(isolate);
    1932             :   v8::Local<v8::FunctionTemplate> func_templ =
    1933           6 :       v8::FunctionTemplate::New(isolate);
    1934          12 :   func_templ->PrototypeTemplate()->Set(
    1935          12 :       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
    1936           6 :   v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
    1937           6 :   templ->Set(isolate, "x", v8_num(200));
    1938           6 :   templ->SetAccessor(v8_str("m"), GetM);
    1939          12 :   LocalContext env(0, templ);
    1940             :   v8::Local<Script> script(v8_compile("dummy()"));
    1941           6 :   v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
    1942          12 :   CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
    1943           6 :   CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
    1944          12 :   CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
    1945           6 : }
    1946             : 
    1947             : 
    1948       23724 : THREADED_TEST(ObjectTemplate) {
    1949           6 :   LocalContext env;
    1950           6 :   v8::Isolate* isolate = CcTest::isolate();
    1951          12 :   v8::HandleScope scope(isolate);
    1952             :   Local<v8::FunctionTemplate> acc =
    1953           6 :       v8::FunctionTemplate::New(isolate, Returns42);
    1954          42 :   CHECK(env->Global()
    1955             :             ->Set(env.local(), v8_str("acc"),
    1956             :                   acc->GetFunction(env.local()).ToLocalChecked())
    1957             :             .FromJust());
    1958             : 
    1959           6 :   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    1960           6 :   v8::Local<v8::String> class_name = v8_str("the_class_name");
    1961           6 :   fun->SetClassName(class_name);
    1962           6 :   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
    1963           6 :   templ1->Set(isolate, "x", v8_num(10));
    1964           6 :   templ1->Set(isolate, "y", v8_num(13));
    1965          12 :   templ1->Set(v8_str("foo"), acc);
    1966             :   Local<v8::Object> instance1 =
    1967           6 :       templ1->NewInstance(env.local()).ToLocalChecked();
    1968          12 :   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
    1969          30 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
    1970          18 :   CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
    1971          18 :   CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
    1972          18 :   CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
    1973          18 :   CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
    1974             :   // Ensure that foo become a data field.
    1975             :   CompileRun("p.foo = function() {}");
    1976           6 :   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
    1977          12 :   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
    1978           6 :   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
    1979           6 :   templ2->Set(isolate, "a", v8_num(12));
    1980             :   templ2->Set(isolate, "b", templ1);
    1981          12 :   templ2->Set(v8_str("bar"), acc);
    1982          12 :   templ2->SetAccessorProperty(v8_str("acc"), acc);
    1983             :   Local<v8::Object> instance2 =
    1984           6 :       templ2->NewInstance(env.local()).ToLocalChecked();
    1985          30 :   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
    1986          18 :   CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
    1987          18 :   CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
    1988          18 :   CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
    1989          18 :   CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
    1990          18 :   CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
    1991          18 :   CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
    1992          18 :   CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
    1993          18 :   CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
    1994          18 :   CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
    1995          18 :   CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
    1996             : 
    1997           6 :   instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
    1998          30 :   CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
    1999          18 :   CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
    2000          18 :   CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
    2001          18 :   CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
    2002          18 :   CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
    2003          18 :   CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
    2004          18 :   CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
    2005          18 :   CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
    2006          18 :   CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
    2007          18 :   CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
    2008             : 
    2009          18 :   CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
    2010          18 :   CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
    2011             :             ->BooleanValue(env.local())
    2012             :             .FromJust());
    2013          18 :   CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
    2014             :                    "(desc1.get === acc)")
    2015             :             ->BooleanValue(env.local())
    2016             :             .FromJust());
    2017          18 :   CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
    2018             :                    "(desc2.get === acc)")
    2019             :             ->BooleanValue(env.local())
    2020           6 :             .FromJust());
    2021           6 : }
    2022             : 
    2023       23724 : THREADED_TEST(IntegerValue) {
    2024           6 :   LocalContext env;
    2025           6 :   v8::Isolate* isolate = CcTest::isolate();
    2026          12 :   v8::HandleScope scope(isolate);
    2027             : 
    2028          24 :   CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
    2029           6 : }
    2030             : 
    2031         126 : static void GetNirk(Local<String> name,
    2032             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2033         126 :   ApiTestFuzzer::Fuzz();
    2034         126 :   info.GetReturnValue().Set(v8_num(900));
    2035         126 : }
    2036             : 
    2037         126 : static void GetRino(Local<String> name,
    2038             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2039         126 :   ApiTestFuzzer::Fuzz();
    2040         126 :   info.GetReturnValue().Set(v8_num(560));
    2041         126 : }
    2042             : 
    2043             : enum ObjectInstantiationMode {
    2044             :   // Create object using ObjectTemplate::NewInstance.
    2045             :   ObjectTemplate_NewInstance,
    2046             :   // Create object using FunctionTemplate::NewInstance on constructor.
    2047             :   Constructor_GetFunction_NewInstance,
    2048             :   // Create object using new operator on constructor.
    2049             :   Constructor_GetFunction_New
    2050             : };
    2051             : 
    2052             : // Test object instance creation using a function template with an instance
    2053             : // template inherited from another function template with accessors and data
    2054             : // properties in prototype template.
    2055          18 : static void TestObjectTemplateInheritedWithPrototype(
    2056             :     ObjectInstantiationMode mode) {
    2057          18 :   LocalContext env;
    2058          18 :   v8::Isolate* isolate = CcTest::isolate();
    2059          36 :   v8::HandleScope scope(isolate);
    2060             : 
    2061          18 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2062          18 :   fun_A->SetClassName(v8_str("A"));
    2063          18 :   v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
    2064          18 :   prototype_templ->Set(isolate, "a", v8_num(113));
    2065          18 :   prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2066          18 :   prototype_templ->Set(isolate, "b", v8_num(153));
    2067             : 
    2068          18 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2069          18 :   v8::Local<v8::String> class_name = v8_str("B");
    2070          18 :   fun_B->SetClassName(class_name);
    2071          18 :   fun_B->Inherit(fun_A);
    2072          18 :   prototype_templ = fun_B->PrototypeTemplate();
    2073          18 :   prototype_templ->Set(isolate, "c", v8_num(713));
    2074          18 :   prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
    2075          18 :   prototype_templ->Set(isolate, "d", v8_num(753));
    2076             : 
    2077          18 :   Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
    2078          18 :   templ->Set(isolate, "x", v8_num(10));
    2079          18 :   templ->Set(isolate, "y", v8_num(13));
    2080             : 
    2081             :   // Perform several iterations to trigger creation from cached boilerplate.
    2082          72 :   for (int i = 0; i < 3; i++) {
    2083             :     Local<v8::Object> instance;
    2084          54 :     switch (mode) {
    2085             :       case ObjectTemplate_NewInstance:
    2086          18 :         instance = templ->NewInstance(env.local()).ToLocalChecked();
    2087          18 :         break;
    2088             : 
    2089             :       case Constructor_GetFunction_NewInstance: {
    2090             :         Local<v8::Function> function_B =
    2091          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2092          18 :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2093             :         break;
    2094             :       }
    2095             :       case Constructor_GetFunction_New: {
    2096             :         Local<v8::Function> function_B =
    2097          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2098          18 :         if (i == 0) {
    2099          24 :           CHECK(env->Global()
    2100             :                     ->Set(env.local(), class_name, function_B)
    2101             :                     .FromJust());
    2102             :         }
    2103             :         instance =
    2104          36 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2105             :         break;
    2106             :       }
    2107             :       default:
    2108           0 :         UNREACHABLE();
    2109             :     }
    2110             : 
    2111         108 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2112         270 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2113             : 
    2114         162 :     CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
    2115         162 :     CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
    2116             : 
    2117         162 :     CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
    2118         162 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2119         162 :     CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
    2120         162 :     CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
    2121         162 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2122         162 :     CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
    2123          18 :   }
    2124          18 : }
    2125             : 
    2126       23724 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
    2127           6 :   TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
    2128           6 : }
    2129             : 
    2130       23724 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
    2131           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
    2132           6 : }
    2133             : 
    2134       23724 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
    2135           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
    2136           6 : }
    2137             : 
    2138             : // Test object instance creation using a function template without an instance
    2139             : // template inherited from another function template.
    2140          12 : static void TestObjectTemplateInheritedWithoutInstanceTemplate(
    2141             :     ObjectInstantiationMode mode) {
    2142          12 :   LocalContext env;
    2143          12 :   v8::Isolate* isolate = CcTest::isolate();
    2144          24 :   v8::HandleScope scope(isolate);
    2145             : 
    2146          12 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2147          12 :   fun_A->SetClassName(v8_str("A"));
    2148             : 
    2149          12 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2150          12 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2151          12 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2152             : 
    2153          12 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2154          12 :   v8::Local<v8::String> class_name = v8_str("B");
    2155          12 :   fun_B->SetClassName(class_name);
    2156          12 :   fun_B->Inherit(fun_A);
    2157             : 
    2158             :   // Perform several iterations to trigger creation from cached boilerplate.
    2159          48 :   for (int i = 0; i < 3; i++) {
    2160             :     Local<v8::Object> instance;
    2161          36 :     switch (mode) {
    2162             :       case Constructor_GetFunction_NewInstance: {
    2163             :         Local<v8::Function> function_B =
    2164          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2165          18 :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2166             :         break;
    2167             :       }
    2168             :       case Constructor_GetFunction_New: {
    2169             :         Local<v8::Function> function_B =
    2170          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2171          18 :         if (i == 0) {
    2172          24 :           CHECK(env->Global()
    2173             :                     ->Set(env.local(), class_name, function_B)
    2174             :                     .FromJust());
    2175             :         }
    2176             :         instance =
    2177          36 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2178             :         break;
    2179             :       }
    2180             :       default:
    2181           0 :         UNREACHABLE();
    2182             :     }
    2183             : 
    2184          72 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2185         180 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2186             : 
    2187         108 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2188         108 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2189          12 :   }
    2190          12 : }
    2191             : 
    2192       23724 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
    2193             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2194           6 :       Constructor_GetFunction_NewInstance);
    2195           6 : }
    2196             : 
    2197       23724 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
    2198             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2199           6 :       Constructor_GetFunction_New);
    2200           6 : }
    2201             : 
    2202       23724 : THREADED_TEST(TestObjectTemplateClassInheritance) {
    2203           6 :   LocalContext env;
    2204           6 :   v8::Isolate* isolate = CcTest::isolate();
    2205          12 :   v8::HandleScope scope(isolate);
    2206             : 
    2207           6 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2208           6 :   fun_A->SetClassName(v8_str("A"));
    2209             : 
    2210           6 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2211           6 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2212           6 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2213             : 
    2214           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2215           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2216           6 :   fun_B->SetClassName(class_name);
    2217           6 :   fun_B->Inherit(fun_A);
    2218             : 
    2219           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2220             :   v8::Local<v8::Object> b_proto;
    2221             :   v8::Local<v8::Object> c_proto;
    2222             :   // Perform several iterations to make sure the cache doesn't break
    2223             :   // subclassing.
    2224          24 :   for (int i = 0; i < 3; i++) {
    2225             :     Local<v8::Function> function_B =
    2226          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2227          18 :     if (i == 0) {
    2228          24 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2229             :       CompileRun("class C extends B {}");
    2230             :       b_proto =
    2231          12 :           CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
    2232             :       c_proto =
    2233          12 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2234          12 :       CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
    2235             :     }
    2236             :     Local<v8::Object> instance =
    2237          36 :         CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
    2238          36 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2239             : 
    2240          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2241          90 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2242             : 
    2243          54 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2244          54 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2245           6 :   }
    2246           6 : }
    2247             : 
    2248         276 : static void NamedPropertyGetterWhichReturns42(
    2249             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2250         276 :   info.GetReturnValue().Set(v8_num(42));
    2251         276 : }
    2252             : 
    2253       23724 : THREADED_TEST(TestObjectTemplateReflectConstruct) {
    2254           6 :   LocalContext env;
    2255           6 :   v8::Isolate* isolate = CcTest::isolate();
    2256          12 :   v8::HandleScope scope(isolate);
    2257             : 
    2258           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2259             :   fun_B->InstanceTemplate()->SetHandler(
    2260          12 :       v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
    2261           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2262           6 :   fun_B->SetClassName(class_name);
    2263             : 
    2264           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2265             :   v8::Local<v8::Object> b_proto;
    2266             :   v8::Local<v8::Object> c_proto;
    2267             :   // Perform several iterations to make sure the cache doesn't break
    2268             :   // subclassing.
    2269          24 :   for (int i = 0; i < 3; i++) {
    2270             :     Local<v8::Function> function_B =
    2271          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2272          18 :     if (i == 0) {
    2273          24 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2274             :       CompileRun("function C() {}");
    2275             :       c_proto =
    2276          12 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2277             :     }
    2278             :     Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
    2279          18 :                                      ->ToObject(env.local())
    2280          18 :                                      .ToLocalChecked();
    2281          36 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2282             : 
    2283          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2284          90 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2285             : 
    2286          54 :     CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2287          54 :     CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2288           6 :   }
    2289           6 : }
    2290             : 
    2291          24 : static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
    2292          12 :   ApiTestFuzzer::Fuzz();
    2293          12 :   args.GetReturnValue().Set(v8_num(17.2));
    2294          12 : }
    2295             : 
    2296             : 
    2297          30 : static void GetKnurd(Local<String> property,
    2298             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    2299          30 :   ApiTestFuzzer::Fuzz();
    2300          30 :   info.GetReturnValue().Set(v8_num(15.2));
    2301          30 : }
    2302             : 
    2303             : 
    2304       23724 : THREADED_TEST(DescriptorInheritance) {
    2305           6 :   v8::Isolate* isolate = CcTest::isolate();
    2306           6 :   v8::HandleScope scope(isolate);
    2307           6 :   v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
    2308          12 :   super->PrototypeTemplate()->Set(isolate, "flabby",
    2309             :                                   v8::FunctionTemplate::New(isolate,
    2310          12 :                                                             GetFlabby));
    2311          12 :   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
    2312             : 
    2313          12 :   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
    2314             : 
    2315           6 :   v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
    2316           6 :   base1->Inherit(super);
    2317          12 :   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
    2318             : 
    2319           6 :   v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
    2320           6 :   base2->Inherit(super);
    2321          12 :   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
    2322             : 
    2323          12 :   LocalContext env;
    2324             : 
    2325          36 :   CHECK(env->Global()
    2326             :             ->Set(env.local(), v8_str("s"),
    2327             :                   super->GetFunction(env.local()).ToLocalChecked())
    2328             :             .FromJust());
    2329          36 :   CHECK(env->Global()
    2330             :             ->Set(env.local(), v8_str("base1"),
    2331             :                   base1->GetFunction(env.local()).ToLocalChecked())
    2332             :             .FromJust());
    2333          36 :   CHECK(env->Global()
    2334             :             ->Set(env.local(), v8_str("base2"),
    2335             :                   base2->GetFunction(env.local()).ToLocalChecked())
    2336             :             .FromJust());
    2337             : 
    2338             :   // Checks right __proto__ chain.
    2339          18 :   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
    2340             :             ->BooleanValue(env.local())
    2341             :             .FromJust());
    2342          18 :   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
    2343             :             ->BooleanValue(env.local())
    2344             :             .FromJust());
    2345             : 
    2346          24 :   CHECK(v8_compile("s.prototype.PI == 3.14")
    2347             :             ->Run(env.local())
    2348             :             .ToLocalChecked()
    2349             :             ->BooleanValue(env.local())
    2350             :             .FromJust());
    2351             : 
    2352             :   // Instance accessor should not be visible on function object or its prototype
    2353          18 :   CHECK(
    2354             :       CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
    2355          18 :   CHECK(CompileRun("s.prototype.knurd == undefined")
    2356             :             ->BooleanValue(env.local())
    2357             :             .FromJust());
    2358          18 :   CHECK(CompileRun("base1.prototype.knurd == undefined")
    2359             :             ->BooleanValue(env.local())
    2360             :             .FromJust());
    2361             : 
    2362          36 :   CHECK(env->Global()
    2363             :             ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
    2364             :                                                   .ToLocalChecked()
    2365             :                                                   ->NewInstance(env.local())
    2366             :                                                   .ToLocalChecked())
    2367             :             .FromJust());
    2368          18 :   CHECK_EQ(17.2,
    2369             :            CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
    2370          18 :   CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
    2371          18 :   CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
    2372          18 :   CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
    2373          18 :   CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
    2374             : 
    2375          36 :   CHECK(env->Global()
    2376             :             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
    2377             :                                                    .ToLocalChecked()
    2378             :                                                    ->NewInstance(env.local())
    2379             :                                                    .ToLocalChecked())
    2380             :             .FromJust());
    2381          18 :   CHECK_EQ(17.2,
    2382             :            CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
    2383          18 :   CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
    2384          18 :   CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
    2385          18 :   CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
    2386          18 :   CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
    2387             : 
    2388             :   // base1 and base2 cannot cross reference to each's prototype
    2389           6 :   CHECK(CompileRun("obj.v2")->IsUndefined());
    2390          12 :   CHECK(CompileRun("obj2.v1")->IsUndefined());
    2391           6 : }
    2392             : 
    2393       23724 : THREADED_TEST(DescriptorInheritance2) {
    2394           6 :   LocalContext env;
    2395           6 :   v8::Isolate* isolate = CcTest::isolate();
    2396          12 :   v8::HandleScope scope(isolate);
    2397           6 :   v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2398           6 :   fun_A->SetClassName(v8_str("A"));
    2399          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
    2400          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
    2401          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
    2402             : 
    2403           6 :   v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2404           6 :   fun_B->SetClassName(v8_str("B"));
    2405           6 :   fun_B->Inherit(fun_A);
    2406             : 
    2407           6 :   v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
    2408           6 :   fun_C->SetClassName(v8_str("C"));
    2409           6 :   fun_C->Inherit(fun_B);
    2410          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
    2411          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
    2412          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
    2413             : 
    2414           6 :   v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
    2415           6 :   fun_D->SetClassName(v8_str("D"));
    2416           6 :   fun_D->Inherit(fun_C);
    2417             : 
    2418           6 :   v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
    2419           6 :   fun_E->SetClassName(v8_str("E"));
    2420           6 :   fun_E->Inherit(fun_D);
    2421          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
    2422          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
    2423          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
    2424             : 
    2425           6 :   v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
    2426           6 :   fun_F->SetClassName(v8_str("F"));
    2427           6 :   fun_F->Inherit(fun_E);
    2428           6 :   v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
    2429             :   const int kDataPropertiesNumber = 100;
    2430         606 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2431         600 :     v8::Local<v8::Value> val = v8_num(i);
    2432        1200 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2433         600 :     v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
    2434             : 
    2435         600 :     templ->Set(name, val);
    2436         600 :     templ->Set(val_str, val);
    2437             :   }
    2438             : 
    2439          36 :   CHECK(env->Global()
    2440             :             ->Set(env.local(), v8_str("F"),
    2441             :                   fun_F->GetFunction(env.local()).ToLocalChecked())
    2442             :             .FromJust());
    2443             : 
    2444             :   v8::Local<v8::Script> script = v8_compile("o = new F()");
    2445             : 
    2446         606 :   for (int i = 0; i < 100; i++) {
    2447         600 :     v8::HandleScope scope(isolate);
    2448         600 :     script->Run(env.local()).ToLocalChecked();
    2449         600 :   }
    2450           6 :   v8::Local<v8::Object> object = script->Run(env.local())
    2451           6 :                                      .ToLocalChecked()
    2452           6 :                                      ->ToObject(env.local())
    2453           6 :                                      .ToLocalChecked();
    2454             : 
    2455          18 :   CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
    2456          18 :   CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
    2457          18 :   CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
    2458             : 
    2459          18 :   CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
    2460          18 :   CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
    2461          18 :   CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
    2462             : 
    2463          18 :   CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
    2464          18 :   CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
    2465          18 :   CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
    2466             : 
    2467         600 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2468         600 :     v8::Local<v8::Value> val = v8_num(i);
    2469        1800 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2470         600 :     v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
    2471             : 
    2472        2400 :     CHECK_EQ(i, object->Get(env.local(), name)
    2473             :                     .ToLocalChecked()
    2474             :                     ->IntegerValue(env.local())
    2475             :                     .FromJust());
    2476        1800 :     CHECK_EQ(i, object->Get(env.local(), val)
    2477             :                     .ToLocalChecked()
    2478             :                     ->IntegerValue(env.local())
    2479             :                     .FromJust());
    2480           6 :   }
    2481           6 : }
    2482             : 
    2483             : 
    2484             : // Helper functions for Interceptor/Accessor interaction tests
    2485             : 
    2486          36 : void SimpleAccessorGetter(Local<String> name,
    2487             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2488             :   Local<Object> self = Local<Object>::Cast(info.This());
    2489             :   info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
    2490         108 :                                       String::Concat(v8_str("accessor_"), name))
    2491          36 :                                 .ToLocalChecked());
    2492          36 : }
    2493             : 
    2494           6 : void SimpleAccessorSetter(Local<String> name, Local<Value> value,
    2495             :                           const v8::PropertyCallbackInfo<void>& info) {
    2496             :   Local<Object> self = Local<Object>::Cast(info.This());
    2497          18 :   CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
    2498             :                   String::Concat(v8_str("accessor_"), name), value)
    2499             :             .FromJust());
    2500           6 : }
    2501             : 
    2502          36 : void SymbolAccessorGetter(Local<Name> name,
    2503             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2504          36 :   CHECK(name->IsSymbol());
    2505             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2506          72 :   if (sym->Name()->IsUndefined())
    2507          36 :     return;
    2508          36 :   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
    2509             : }
    2510             : 
    2511           6 : void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
    2512             :                           const v8::PropertyCallbackInfo<void>& info) {
    2513           6 :   CHECK(name->IsSymbol());
    2514             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2515          12 :   if (sym->Name()->IsUndefined())
    2516           6 :     return;
    2517           6 :   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
    2518             : }
    2519             : 
    2520           5 : void SymbolAccessorGetterReturnsDefault(
    2521             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2522           5 :   CHECK(name->IsSymbol());
    2523             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2524          15 :   if (sym->Name()->IsUndefined()) return;
    2525             :   info.GetReturnValue().Set(info.Data());
    2526             : }
    2527             : 
    2528           5 : static void ThrowingSymbolAccessorGetter(
    2529             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2530          10 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
    2531           5 : }
    2532             : 
    2533             : 
    2534       23724 : THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
    2535           6 :   v8::Isolate* isolate = CcTest::isolate();
    2536           6 :   v8::HandleScope scope(isolate);
    2537          12 :   LocalContext env;
    2538             :   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
    2539             :   i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
    2540           6 :   CHECK_EQ(1, a->map()->instance_descriptors()->number_of_descriptors());
    2541             :   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
    2542           6 :   CHECK_EQ(0, a->map()->instance_descriptors()->number_of_descriptors());
    2543             :   // But we should still have an AccessorInfo.
    2544          12 :   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
    2545           6 :   i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
    2546           6 :   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
    2547          18 :   CHECK(it.GetAccessors()->IsAccessorInfo());
    2548           6 : }
    2549             : 
    2550             : 
    2551       23724 : THREADED_TEST(UndefinedIsNotEnumerable) {
    2552           6 :   LocalContext env;
    2553          12 :   v8::HandleScope scope(env->GetIsolate());
    2554             :   v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
    2555          12 :   CHECK(result->IsFalse());
    2556           6 : }
    2557             : 
    2558             : 
    2559             : v8::Local<Script> call_recursively_script;
    2560             : static const int kTargetRecursionDepth = 100;  // near maximum
    2561             : 
    2562         606 : static void CallScriptRecursivelyCall(
    2563        3012 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2564         606 :   ApiTestFuzzer::Fuzz();
    2565         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2566             :   int depth = args.This()
    2567        1212 :                   ->Get(context, v8_str("depth"))
    2568         606 :                   .ToLocalChecked()
    2569             :                   ->Int32Value(context)
    2570        1212 :                   .FromJust();
    2571         612 :   if (depth == kTargetRecursionDepth) return;
    2572        3000 :   CHECK(args.This()
    2573             :             ->Set(context, v8_str("depth"),
    2574             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2575             :             .FromJust());
    2576             :   args.GetReturnValue().Set(
    2577         600 :       call_recursively_script->Run(context).ToLocalChecked());
    2578             : }
    2579             : 
    2580             : 
    2581         606 : static void CallFunctionRecursivelyCall(
    2582        4212 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2583         606 :   ApiTestFuzzer::Fuzz();
    2584         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2585             :   int depth = args.This()
    2586        1212 :                   ->Get(context, v8_str("depth"))
    2587         606 :                   .ToLocalChecked()
    2588             :                   ->Int32Value(context)
    2589        1212 :                   .FromJust();
    2590         606 :   if (depth == kTargetRecursionDepth) {
    2591             :     printf("[depth = %d]\n", depth);
    2592         612 :     return;
    2593             :   }
    2594        3000 :   CHECK(args.This()
    2595             :             ->Set(context, v8_str("depth"),
    2596             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2597             :             .FromJust());
    2598             :   v8::Local<Value> function =
    2599             :       args.This()
    2600        1200 :           ->Get(context, v8_str("callFunctionRecursively"))
    2601         600 :           .ToLocalChecked();
    2602             :   args.GetReturnValue().Set(function.As<Function>()
    2603         600 :                                 ->Call(context, args.This(), 0, nullptr)
    2604         600 :                                 .ToLocalChecked());
    2605             : }
    2606             : 
    2607             : 
    2608       23724 : THREADED_TEST(DeepCrossLanguageRecursion) {
    2609           6 :   v8::Isolate* isolate = CcTest::isolate();
    2610           6 :   v8::HandleScope scope(isolate);
    2611           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    2612             :   global->Set(v8_str("callScriptRecursively"),
    2613          18 :               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
    2614             :   global->Set(v8_str("callFunctionRecursively"),
    2615          18 :               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
    2616          12 :   LocalContext env(nullptr, global);
    2617             : 
    2618          36 :   CHECK(env->Global()
    2619             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2620             :             .FromJust());
    2621           6 :   call_recursively_script = v8_compile("callScriptRecursively()");
    2622          12 :   call_recursively_script->Run(env.local()).ToLocalChecked();
    2623           6 :   call_recursively_script = v8::Local<Script>();
    2624             : 
    2625          36 :   CHECK(env->Global()
    2626             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2627             :             .FromJust());
    2628           6 :   CompileRun("callFunctionRecursively()");
    2629           6 : }
    2630             : 
    2631             : 
    2632          24 : static void ThrowingPropertyHandlerGet(
    2633             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2634             :   // Since this interceptor is used on "with" objects, the runtime will look up
    2635             :   // @@unscopables.  Punt.
    2636          48 :   if (key->IsSymbol()) return;
    2637          12 :   ApiTestFuzzer::Fuzz();
    2638          24 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
    2639             : }
    2640             : 
    2641             : 
    2642           0 : static void ThrowingPropertyHandlerSet(
    2643             :     Local<Name> key, Local<Value>,
    2644             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2645           0 :   info.GetIsolate()->ThrowException(key);
    2646             :   info.GetReturnValue().SetUndefined();  // not the same as empty handle
    2647           0 : }
    2648             : 
    2649             : 
    2650       23724 : THREADED_TEST(CallbackExceptionRegression) {
    2651           6 :   v8::Isolate* isolate = CcTest::isolate();
    2652           6 :   v8::HandleScope scope(isolate);
    2653           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    2654             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2655           6 :       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
    2656          12 :   LocalContext env;
    2657          36 :   CHECK(env->Global()
    2658             :             ->Set(env.local(), v8_str("obj"),
    2659             :                   obj->NewInstance(env.local()).ToLocalChecked())
    2660             :             .FromJust());
    2661             :   v8::Local<Value> otto =
    2662           6 :       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
    2663          18 :   CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
    2664             :   v8::Local<Value> netto =
    2665           6 :       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
    2666          24 :   CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
    2667           6 : }
    2668             : 
    2669             : 
    2670       23724 : THREADED_TEST(FunctionPrototype) {
    2671           6 :   v8::Isolate* isolate = CcTest::isolate();
    2672           6 :   v8::HandleScope scope(isolate);
    2673           6 :   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
    2674          24 :   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
    2675          12 :   LocalContext env;
    2676          36 :   CHECK(env->Global()
    2677             :             ->Set(env.local(), v8_str("Foo"),
    2678             :                   Foo->GetFunction(env.local()).ToLocalChecked())
    2679             :             .FromJust());
    2680           6 :   Local<Script> script = v8_compile("Foo.prototype.plak");
    2681          12 :   CHECK_EQ(v8_run_int32value(script), 321);
    2682           6 : }
    2683             : 
    2684       23724 : THREADED_TEST(InternalFields) {
    2685           6 :   LocalContext env;
    2686           6 :   v8::Isolate* isolate = env->GetIsolate();
    2687          12 :   v8::HandleScope scope(isolate);
    2688             : 
    2689           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2690           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2691           6 :   instance_templ->SetInternalFieldCount(1);
    2692           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2693           6 :                               .ToLocalChecked()
    2694           6 :                               ->NewInstance(env.local())
    2695             :                               .ToLocalChecked();
    2696           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2697           6 :   CHECK(obj->GetInternalField(0)->IsUndefined());
    2698           6 :   obj->SetInternalField(0, v8_num(17));
    2699          24 :   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2700           6 : }
    2701             : 
    2702       23724 : THREADED_TEST(InternalFieldsOfRegularObjects) {
    2703           6 :   LocalContext env;
    2704           6 :   v8::Isolate* isolate = env->GetIsolate();
    2705          12 :   v8::HandleScope scope(isolate);
    2706             : 
    2707           6 :   const char* sources[] = {"new Object()", "{ a: 'a property' }", "arguments"};
    2708          24 :   for (size_t i = 0; i < arraysize(sources); ++i) {
    2709             :     i::ScopedVector<char> source(128);
    2710          18 :     i::SNPrintF(source, "(function() { return %s })()", sources[i]);
    2711             :     v8::Local<v8::Object> obj = CompileRun(source.start()).As<v8::Object>();
    2712          18 :     CHECK_EQ(0, obj->InternalFieldCount());
    2713           6 :   }
    2714           6 : }
    2715             : 
    2716       23724 : THREADED_TEST(GlobalObjectInternalFields) {
    2717           6 :   v8::Isolate* isolate = CcTest::isolate();
    2718           6 :   v8::HandleScope scope(isolate);
    2719           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
    2720           6 :   global_template->SetInternalFieldCount(1);
    2721          12 :   LocalContext env(nullptr, global_template);
    2722           6 :   v8::Local<v8::Object> global_proxy = env->Global();
    2723           6 :   v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
    2724           6 :   CHECK_EQ(1, global->InternalFieldCount());
    2725           6 :   CHECK(global->GetInternalField(0)->IsUndefined());
    2726           6 :   global->SetInternalField(0, v8_num(17));
    2727          24 :   CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2728           6 : }
    2729             : 
    2730             : 
    2731       23724 : THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
    2732           6 :   LocalContext env;
    2733          12 :   v8::HandleScope scope(CcTest::isolate());
    2734             : 
    2735           6 :   v8::Local<v8::Object> global = env->Global();
    2736          18 :   CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
    2737          18 :   CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
    2738           6 : }
    2739             : 
    2740          24 : static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
    2741             :                                                void* value) {
    2742          24 :   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
    2743          24 :   obj->SetAlignedPointerInInternalField(0, value);
    2744          24 :   CcTest::CollectAllGarbage();
    2745          24 :   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
    2746          24 : }
    2747             : 
    2748       23724 : THREADED_TEST(InternalFieldsAlignedPointers) {
    2749           6 :   LocalContext env;
    2750           6 :   v8::Isolate* isolate = env->GetIsolate();
    2751          12 :   v8::HandleScope scope(isolate);
    2752             : 
    2753           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2754           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2755           6 :   instance_templ->SetInternalFieldCount(1);
    2756           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2757           6 :                               .ToLocalChecked()
    2758           6 :                               ->NewInstance(env.local())
    2759             :                               .ToLocalChecked();
    2760           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2761             : 
    2762           6 :   CheckAlignedPointerInInternalField(obj, nullptr);
    2763             : 
    2764           6 :   int* heap_allocated = new int[100];
    2765           6 :   CheckAlignedPointerInInternalField(obj, heap_allocated);
    2766           6 :   delete[] heap_allocated;
    2767             : 
    2768             :   int stack_allocated[100];
    2769           6 :   CheckAlignedPointerInInternalField(obj, stack_allocated);
    2770             : 
    2771             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2772           6 :   CheckAlignedPointerInInternalField(obj, huge);
    2773             : 
    2774             :   v8::Global<v8::Object> persistent(isolate, obj);
    2775           6 :   CHECK_EQ(1, Object::InternalFieldCount(persistent));
    2776          12 :   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
    2777           6 : }
    2778             : 
    2779       23724 : THREADED_TEST(SetAlignedPointerInInternalFields) {
    2780           6 :   LocalContext env;
    2781           6 :   v8::Isolate* isolate = env->GetIsolate();
    2782          12 :   v8::HandleScope scope(isolate);
    2783             : 
    2784           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2785           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2786           6 :   instance_templ->SetInternalFieldCount(2);
    2787           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2788           6 :                               .ToLocalChecked()
    2789           6 :                               ->NewInstance(env.local())
    2790             :                               .ToLocalChecked();
    2791           6 :   CHECK_EQ(2, obj->InternalFieldCount());
    2792             : 
    2793           6 :   int* heap_allocated_1 = new int[100];
    2794           6 :   int* heap_allocated_2 = new int[100];
    2795           6 :   int indices[] = {0, 1};
    2796           6 :   void* values[] = {heap_allocated_1, heap_allocated_2};
    2797             : 
    2798           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2799           6 :   CcTest::CollectAllGarbage();
    2800           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(0));
    2801           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(1));
    2802             : 
    2803           6 :   indices[0] = 1;
    2804           6 :   indices[1] = 0;
    2805           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2806           6 :   CcTest::CollectAllGarbage();
    2807           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(0));
    2808           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(1));
    2809             : 
    2810           6 :   delete[] heap_allocated_1;
    2811          12 :   delete[] heap_allocated_2;
    2812           6 : }
    2813             : 
    2814          24 : static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
    2815             :                                               void* value) {
    2816          24 :   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
    2817          24 :   (*env)->SetAlignedPointerInEmbedderData(index, value);
    2818          24 :   CcTest::CollectAllGarbage();
    2819          24 :   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
    2820          24 : }
    2821             : 
    2822             : 
    2823             : static void* AlignedTestPointer(int i) {
    2824        1200 :   return reinterpret_cast<void*>(i * 1234);
    2825             : }
    2826             : 
    2827             : 
    2828       23724 : THREADED_TEST(EmbedderDataAlignedPointers) {
    2829           6 :   LocalContext env;
    2830          12 :   v8::HandleScope scope(env->GetIsolate());
    2831             : 
    2832           6 :   CheckAlignedPointerInEmbedderData(&env, 0, nullptr);
    2833             : 
    2834           6 :   int* heap_allocated = new int[100];
    2835           6 :   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
    2836           6 :   delete[] heap_allocated;
    2837             : 
    2838             :   int stack_allocated[100];
    2839           6 :   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
    2840             : 
    2841             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2842           6 :   CheckAlignedPointerInEmbedderData(&env, 3, huge);
    2843             : 
    2844             :   // Test growing of the embedder data's backing store.
    2845         606 :   for (int i = 0; i < 100; i++) {
    2846         600 :     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
    2847             :   }
    2848           6 :   CcTest::CollectAllGarbage();
    2849         606 :   for (int i = 0; i < 100; i++) {
    2850         600 :     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
    2851           6 :   }
    2852           6 : }
    2853             : 
    2854          24 : static void CheckEmbedderData(LocalContext* env, int index,
    2855             :                               v8::Local<Value> data) {
    2856          24 :   (*env)->SetEmbedderData(index, data);
    2857          24 :   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
    2858          24 : }
    2859             : 
    2860             : 
    2861       23724 : THREADED_TEST(EmbedderData) {
    2862           6 :   LocalContext env;
    2863           6 :   v8::Isolate* isolate = env->GetIsolate();
    2864          12 :   v8::HandleScope scope(isolate);
    2865             : 
    2866          12 :   CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
    2867          12 :   CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
    2868          12 :   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
    2869          12 :   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
    2870           6 : }
    2871             : 
    2872             : 
    2873       23724 : THREADED_TEST(IdentityHash) {
    2874           6 :   LocalContext env;
    2875           6 :   v8::Isolate* isolate = env->GetIsolate();
    2876          12 :   v8::HandleScope scope(isolate);
    2877             : 
    2878             :   // Ensure that the test starts with an fresh heap to test whether the hash
    2879             :   // code is based on the address.
    2880           6 :   CcTest::CollectAllGarbage();
    2881           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
    2882           6 :   int hash = obj->GetIdentityHash();
    2883           6 :   int hash1 = obj->GetIdentityHash();
    2884           6 :   CHECK_EQ(hash, hash1);
    2885          12 :   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
    2886             :   // Since the identity hash is essentially a random number two consecutive
    2887             :   // objects should not be assigned the same hash code. If the test below fails
    2888             :   // the random number generator should be evaluated.
    2889           6 :   CHECK_NE(hash, hash2);
    2890           6 :   CcTest::CollectAllGarbage();
    2891          12 :   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
    2892             :   // Make sure that the identity hash is not based on the initial address of
    2893             :   // the object alone. If the test below fails the random number generator
    2894             :   // should be evaluated.
    2895           6 :   CHECK_NE(hash, hash3);
    2896           6 :   int hash4 = obj->GetIdentityHash();
    2897           6 :   CHECK_EQ(hash, hash4);
    2898             : 
    2899             :   // Check identity hashes behaviour in the presence of JS accessors.
    2900             :   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
    2901             :   {
    2902             :     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
    2903           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    2904           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    2905          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    2906             :   }
    2907             :   {
    2908             :     CompileRun(
    2909             :         "function cnst() { return 42; };\n"
    2910             :         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
    2911           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    2912           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    2913          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    2914           6 :   }
    2915           6 : }
    2916             : 
    2917             : 
    2918          12 : void GlobalProxyIdentityHash(bool set_in_js) {
    2919          12 :   LocalContext env;
    2920          12 :   v8::Isolate* isolate = env->GetIsolate();
    2921             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    2922          24 :   v8::HandleScope scope(isolate);
    2923          12 :   Local<Object> global_proxy = env->Global();
    2924             :   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
    2925          60 :   CHECK(env->Global()
    2926             :             ->Set(env.local(), v8_str("global"), global_proxy)
    2927             :             .FromJust());
    2928             :   int32_t hash1;
    2929          12 :   if (set_in_js) {
    2930             :     CompileRun("var m = new Set(); m.add(global);");
    2931           6 :     i::Object* original_hash = i_global_proxy->GetHash();
    2932           6 :     CHECK(original_hash->IsSmi());
    2933             :     hash1 = i::Smi::ToInt(original_hash);
    2934             :   } else {
    2935           6 :     hash1 = i_global_proxy->GetOrCreateHash(i_isolate)->value();
    2936             :   }
    2937             :   // Hash should be retained after being detached.
    2938          12 :   env->DetachGlobal();
    2939          12 :   int hash2 = global_proxy->GetIdentityHash();
    2940          12 :   CHECK_EQ(hash1, hash2);
    2941             :   {
    2942             :     // Re-attach global proxy to a new context, hash should stay the same.
    2943          12 :     LocalContext env2(nullptr, Local<ObjectTemplate>(), global_proxy);
    2944          12 :     int hash3 = global_proxy->GetIdentityHash();
    2945          12 :     CHECK_EQ(hash1, hash3);
    2946          12 :   }
    2947          12 : }
    2948             : 
    2949             : 
    2950       23724 : THREADED_TEST(GlobalProxyIdentityHash) {
    2951           6 :   GlobalProxyIdentityHash(true);
    2952           6 :   GlobalProxyIdentityHash(false);
    2953           6 : }
    2954             : 
    2955             : 
    2956       23723 : TEST(SymbolIdentityHash) {
    2957           5 :   LocalContext env;
    2958           5 :   v8::Isolate* isolate = env->GetIsolate();
    2959          10 :   v8::HandleScope scope(isolate);
    2960             : 
    2961             :   {
    2962           5 :     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
    2963           5 :     int hash = symbol->GetIdentityHash();
    2964           5 :     int hash1 = symbol->GetIdentityHash();
    2965           5 :     CHECK_EQ(hash, hash1);
    2966           5 :     CcTest::CollectAllGarbage();
    2967           5 :     int hash3 = symbol->GetIdentityHash();
    2968           5 :     CHECK_EQ(hash, hash3);
    2969             :   }
    2970             : 
    2971             :   {
    2972             :     v8::Local<v8::Symbol> js_symbol =
    2973             :         CompileRun("Symbol('foo')").As<v8::Symbol>();
    2974           5 :     int hash = js_symbol->GetIdentityHash();
    2975           5 :     int hash1 = js_symbol->GetIdentityHash();
    2976           5 :     CHECK_EQ(hash, hash1);
    2977           5 :     CcTest::CollectAllGarbage();
    2978           5 :     int hash3 = js_symbol->GetIdentityHash();
    2979           5 :     CHECK_EQ(hash, hash3);
    2980           5 :   }
    2981           5 : }
    2982             : 
    2983             : 
    2984       23723 : TEST(StringIdentityHash) {
    2985           5 :   LocalContext env;
    2986           5 :   v8::Isolate* isolate = env->GetIsolate();
    2987          10 :   v8::HandleScope scope(isolate);
    2988             : 
    2989           5 :   Local<v8::String> str = v8_str("str1");
    2990           5 :   int hash = str->GetIdentityHash();
    2991           5 :   int hash1 = str->GetIdentityHash();
    2992           5 :   CHECK_EQ(hash, hash1);
    2993           5 :   CcTest::CollectAllGarbage();
    2994           5 :   int hash3 = str->GetIdentityHash();
    2995           5 :   CHECK_EQ(hash, hash3);
    2996             : 
    2997           5 :   Local<v8::String> str2 = v8_str("str1");
    2998           5 :   int hash4 = str2->GetIdentityHash();
    2999          10 :   CHECK_EQ(hash, hash4);
    3000           5 : }
    3001             : 
    3002             : 
    3003       23724 : THREADED_TEST(SymbolProperties) {
    3004           6 :   LocalContext env;
    3005           6 :   v8::Isolate* isolate = env->GetIsolate();
    3006          12 :   v8::HandleScope scope(isolate);
    3007             : 
    3008           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3009           6 :   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
    3010           6 :   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
    3011           6 :   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
    3012           6 :   v8::Local<v8::Symbol> sym4 = v8::Symbol::New(isolate, v8_str("native"));
    3013             : 
    3014           6 :   CcTest::CollectAllGarbage();
    3015             : 
    3016             :   // Check basic symbol functionality.
    3017           6 :   CHECK(sym1->IsSymbol());
    3018           6 :   CHECK(sym2->IsSymbol());
    3019           6 :   CHECK(!obj->IsSymbol());
    3020             : 
    3021          12 :   CHECK(sym1->Equals(env.local(), sym1).FromJust());
    3022          12 :   CHECK(sym2->Equals(env.local(), sym2).FromJust());
    3023          12 :   CHECK(!sym1->Equals(env.local(), sym2).FromJust());
    3024          12 :   CHECK(!sym2->Equals(env.local(), sym1).FromJust());
    3025           6 :   CHECK(sym1->StrictEquals(sym1));
    3026           6 :   CHECK(sym2->StrictEquals(sym2));
    3027           6 :   CHECK(!sym1->StrictEquals(sym2));
    3028           6 :   CHECK(!sym2->StrictEquals(sym1));
    3029             : 
    3030          24 :   CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
    3031             : 
    3032             :   v8::Local<v8::Value> sym_val = sym2;
    3033           6 :   CHECK(sym_val->IsSymbol());
    3034          12 :   CHECK(sym_val->Equals(env.local(), sym2).FromJust());
    3035           6 :   CHECK(sym_val->StrictEquals(sym2));
    3036          12 :   CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
    3037             : 
    3038           6 :   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
    3039           6 :   CHECK(sym_obj->IsSymbolObject());
    3040           6 :   CHECK(!sym2->IsSymbolObject());
    3041           6 :   CHECK(!obj->IsSymbolObject());
    3042          12 :   CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
    3043           6 :   CHECK(!sym_obj->StrictEquals(sym2));
    3044          12 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3045             :             ->Equals(env.local(), sym_obj)
    3046             :             .FromJust());
    3047          18 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3048             :             ->ValueOf()
    3049             :             ->Equals(env.local(), sym2)
    3050             :             .FromJust());
    3051             : 
    3052             :   // Make sure delete of a non-existent symbol property works.
    3053          12 :   CHECK(obj->Delete(env.local(), sym1).FromJust());
    3054          12 :   CHECK(!obj->Has(env.local(), sym1).FromJust());
    3055             : 
    3056          18 :   CHECK(
    3057             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
    3058          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3059          24 :   CHECK_EQ(1503, obj->Get(env.local(), sym1)
    3060             :                      .ToLocalChecked()
    3061             :                      ->Int32Value(env.local())
    3062             :                      .FromJust());
    3063          18 :   CHECK(
    3064             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
    3065          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3066          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3067             :                      .ToLocalChecked()
    3068             :                      ->Int32Value(env.local())
    3069             :                      .FromJust());
    3070          12 :   CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
    3071             : 
    3072          12 :   CHECK_EQ(0u,
    3073             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3074             :   unsigned num_props =
    3075          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3076          24 :   CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
    3077             :             .FromJust());
    3078          12 :   CHECK_EQ(1u,
    3079             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3080          12 :   CHECK_EQ(num_props + 1,
    3081             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3082             : 
    3083           6 :   CcTest::CollectAllGarbage();
    3084             : 
    3085          12 :   CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
    3086             :                          SymbolAccessorSetter)
    3087             :             .FromJust());
    3088          12 :   CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
    3089          18 :   CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
    3090          30 :   CHECK(obj->Get(env.local(), sym3)
    3091             :             .ToLocalChecked()
    3092             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3093             :             .FromJust());
    3094          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3095             :             .ToLocalChecked()
    3096             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3097             :             .FromJust());
    3098             : 
    3099          12 :   CHECK(obj->SetNativeDataProperty(env.local(), sym4, SymbolAccessorGetter)
    3100             :             .FromJust());
    3101          12 :   CHECK(obj->Get(env.local(), sym4).ToLocalChecked()->IsUndefined());
    3102          24 :   CHECK(obj->Set(env.local(), v8_str("accessor_native"),
    3103             :                  v8::Integer::New(isolate, 123))
    3104             :             .FromJust());
    3105          24 :   CHECK_EQ(123, obj->Get(env.local(), sym4)
    3106             :                     .ToLocalChecked()
    3107             :                     ->Int32Value(env.local())
    3108             :                     .FromJust());
    3109          18 :   CHECK(obj->Set(env.local(), sym4, v8::Integer::New(isolate, 314)).FromJust());
    3110          30 :   CHECK(obj->Get(env.local(), sym4)
    3111             :             .ToLocalChecked()
    3112             :             ->Equals(env.local(), v8::Integer::New(isolate, 314))
    3113             :             .FromJust());
    3114          18 :   CHECK(obj->Delete(env.local(), v8_str("accessor_native")).FromJust());
    3115             : 
    3116             :   // Add another property and delete it afterwards to force the object in
    3117             :   // slow case.
    3118          18 :   CHECK(
    3119             :       obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
    3120          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3121             :                      .ToLocalChecked()
    3122             :                      ->Int32Value(env.local())
    3123             :                      .FromJust());
    3124          24 :   CHECK_EQ(2008, obj->Get(env.local(), sym2)
    3125             :                      .ToLocalChecked()
    3126             :                      ->Int32Value(env.local())
    3127             :                      .FromJust());
    3128          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3129             :                      .ToLocalChecked()
    3130             :                      ->Int32Value(env.local())
    3131             :                      .FromJust());
    3132          12 :   CHECK_EQ(2u,
    3133             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3134             : 
    3135          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3136          12 :   CHECK(obj->Has(env.local(), sym2).FromJust());
    3137          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3138          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3139          12 :   CHECK(obj->Delete(env.local(), sym2).FromJust());
    3140          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3141          12 :   CHECK(!obj->Has(env.local(), sym2).FromJust());
    3142          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3143          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3144          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3145             :                      .ToLocalChecked()
    3146             :                      ->Int32Value(env.local())
    3147             :                      .FromJust());
    3148          30 :   CHECK(obj->Get(env.local(), sym3)
    3149             :             .ToLocalChecked()
    3150             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3151             :             .FromJust());
    3152          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3153             :             .ToLocalChecked()
    3154             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3155             :             .FromJust());
    3156          12 :   CHECK_EQ(2u,
    3157             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3158             : 
    3159             :   // Symbol properties are inherited.
    3160           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3161          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3162          12 :   CHECK(child->Has(env.local(), sym1).FromJust());
    3163          24 :   CHECK_EQ(2002, child->Get(env.local(), sym1)
    3164             :                      .ToLocalChecked()
    3165             :                      ->Int32Value(env.local())
    3166             :                      .FromJust());
    3167          30 :   CHECK(obj->Get(env.local(), sym3)
    3168             :             .ToLocalChecked()
    3169             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3170             :             .FromJust());
    3171          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3172             :             .ToLocalChecked()
    3173             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3174             :             .FromJust());
    3175          12 :   CHECK_EQ(0u,
    3176           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3177           6 : }
    3178             : 
    3179             : 
    3180       23724 : THREADED_TEST(SymbolTemplateProperties) {
    3181           6 :   LocalContext env;
    3182           6 :   v8::Isolate* isolate = env->GetIsolate();
    3183          12 :   v8::HandleScope scope(isolate);
    3184           6 :   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
    3185           6 :   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
    3186           6 :   CHECK(!name.IsEmpty());
    3187          18 :   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
    3188             :   v8::Local<v8::Object> new_instance =
    3189          18 :       foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    3190           6 :   CHECK(!new_instance.IsEmpty());
    3191          18 :   CHECK(new_instance->Has(env.local(), name).FromJust());
    3192           6 : }
    3193             : 
    3194             : 
    3195       23724 : THREADED_TEST(PrivatePropertiesOnProxies) {
    3196           6 :   LocalContext env;
    3197           6 :   v8::Isolate* isolate = env->GetIsolate();
    3198          12 :   v8::HandleScope scope(isolate);
    3199             : 
    3200           6 :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
    3201           6 :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
    3202             : 
    3203             :   v8::Local<v8::Proxy> proxy =
    3204           6 :       v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
    3205             : 
    3206           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3207             :   v8::Local<v8::Private> priv2 =
    3208           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3209             : 
    3210           6 :   CcTest::CollectAllGarbage();
    3211             : 
    3212          30 :   CHECK(priv2->Name()
    3213             :             ->Equals(env.local(),
    3214             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3215             :                                              v8::NewStringType::kNormal)
    3216             :                          .ToLocalChecked())
    3217             :             .FromJust());
    3218             : 
    3219             :   // Make sure delete of a non-existent private symbol property works.
    3220          12 :   proxy->DeletePrivate(env.local(), priv1).FromJust();
    3221          12 :   CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
    3222             : 
    3223          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3224             :             .FromJust());
    3225          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3226          18 :   CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
    3227             :                      .ToLocalChecked()
    3228             :                      ->Int32Value(env.local())
    3229             :                      .FromJust());
    3230          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3231             :             .FromJust());
    3232          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3233          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3234             :                      .ToLocalChecked()
    3235             :                      ->Int32Value(env.local())
    3236             :                      .FromJust());
    3237             : 
    3238          12 :   CHECK_EQ(0u,
    3239             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3240             :   unsigned num_props =
    3241          12 :       proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3242          24 :   CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
    3243             :                                     isolate, "bla", v8::NewStringType::kNormal)
    3244             :                                     .ToLocalChecked(),
    3245             :                    v8::Integer::New(isolate, 20))
    3246             :             .FromJust());
    3247          12 :   CHECK_EQ(1u,
    3248             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3249          12 :   CHECK_EQ(num_props + 1,
    3250             :            proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3251             : 
    3252           6 :   CcTest::CollectAllGarbage();
    3253             : 
    3254             :   // Add another property and delete it afterwards to force the object in
    3255             :   // slow case.
    3256          18 :   CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3257             :             .FromJust());
    3258          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3259             :                      .ToLocalChecked()
    3260             :                      ->Int32Value(env.local())
    3261             :                      .FromJust());
    3262          18 :   CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
    3263             :                      .ToLocalChecked()
    3264             :                      ->Int32Value(env.local())
    3265             :                      .FromJust());
    3266          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3267             :                      .ToLocalChecked()
    3268             :                      ->Int32Value(env.local())
    3269             :                      .FromJust());
    3270          12 :   CHECK_EQ(1u,
    3271             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3272             : 
    3273          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3274          12 :   CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
    3275          12 :   CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
    3276          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3277          12 :   CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
    3278          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3279             :                      .ToLocalChecked()
    3280             :                      ->Int32Value(env.local())
    3281             :                      .FromJust());
    3282          12 :   CHECK_EQ(1u,
    3283             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3284             : 
    3285             :   // Private properties are not inherited (for the time being).
    3286           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3287          12 :   CHECK(child->SetPrototype(env.local(), proxy).FromJust());
    3288          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3289          12 :   CHECK_EQ(0u,
    3290           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3291           6 : }
    3292             : 
    3293             : 
    3294       23724 : THREADED_TEST(PrivateProperties) {
    3295           6 :   LocalContext env;
    3296           6 :   v8::Isolate* isolate = env->GetIsolate();
    3297          12 :   v8::HandleScope scope(isolate);
    3298             : 
    3299           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3300           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3301             :   v8::Local<v8::Private> priv2 =
    3302           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3303             : 
    3304           6 :   CcTest::CollectAllGarbage();
    3305             : 
    3306          30 :   CHECK(priv2->Name()
    3307             :             ->Equals(env.local(),
    3308             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3309             :                                              v8::NewStringType::kNormal)
    3310             :                          .ToLocalChecked())
    3311             :             .FromJust());
    3312             : 
    3313             :   // Make sure delete of a non-existent private symbol property works.
    3314          12 :   obj->DeletePrivate(env.local(), priv1).FromJust();
    3315          12 :   CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
    3316             : 
    3317          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3318             :             .FromJust());
    3319          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3320          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
    3321             :                      .ToLocalChecked()
    3322             :                      ->Int32Value(env.local())
    3323             :                      .FromJust());
    3324          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3325             :             .FromJust());
    3326          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3327          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3328             :                      .ToLocalChecked()
    3329             :                      ->Int32Value(env.local())
    3330             :                      .FromJust());
    3331             : 
    3332          12 :   CHECK_EQ(0u,
    3333             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3334             :   unsigned num_props =
    3335          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3336          24 :   CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
    3337             :                                   isolate, "bla", v8::NewStringType::kNormal)
    3338             :                                   .ToLocalChecked(),
    3339             :                  v8::Integer::New(isolate, 20))
    3340             :             .FromJust());
    3341          12 :   CHECK_EQ(1u,
    3342             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3343          12 :   CHECK_EQ(num_props + 1,
    3344             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3345             : 
    3346           6 :   CcTest::CollectAllGarbage();
    3347             : 
    3348             :   // Add another property and delete it afterwards to force the object in
    3349             :   // slow case.
    3350          18 :   CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3351             :             .FromJust());
    3352          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3353             :                      .ToLocalChecked()
    3354             :                      ->Int32Value(env.local())
    3355             :                      .FromJust());
    3356          18 :   CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
    3357             :                      .ToLocalChecked()
    3358             :                      ->Int32Value(env.local())
    3359             :                      .FromJust());
    3360          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3361             :                      .ToLocalChecked()
    3362             :                      ->Int32Value(env.local())
    3363             :                      .FromJust());
    3364          12 :   CHECK_EQ(1u,
    3365             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3366             : 
    3367          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3368          12 :   CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
    3369          12 :   CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
    3370          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3371          12 :   CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
    3372          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3373             :                      .ToLocalChecked()
    3374             :                      ->Int32Value(env.local())
    3375             :                      .FromJust());
    3376          12 :   CHECK_EQ(1u,
    3377             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3378             : 
    3379             :   // Private properties are not inherited (for the time being).
    3380           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3381          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3382          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3383          12 :   CHECK_EQ(0u,
    3384           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3385           6 : }
    3386             : 
    3387             : 
    3388       23724 : THREADED_TEST(GlobalSymbols) {
    3389           6 :   LocalContext env;
    3390           6 :   v8::Isolate* isolate = env->GetIsolate();
    3391          12 :   v8::HandleScope scope(isolate);
    3392             : 
    3393           6 :   v8::Local<String> name = v8_str("my-symbol");
    3394           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3395           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3396           6 :   CHECK(glob2->SameValue(glob));
    3397             : 
    3398           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3399           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3400           6 :   CHECK(glob_api2->SameValue(glob_api));
    3401           6 :   CHECK(!glob_api->SameValue(glob));
    3402             : 
    3403           6 :   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
    3404           6 :   CHECK(!sym->SameValue(glob));
    3405             : 
    3406             :   CompileRun("var sym2 = Symbol.for('my-symbol')");
    3407             :   v8::Local<Value> sym2 =
    3408          30 :       env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
    3409           6 :   CHECK(sym2->SameValue(glob));
    3410          12 :   CHECK(!sym2->SameValue(glob_api));
    3411           6 : }
    3412             : 
    3413       23724 : THREADED_TEST(GlobalSymbolsNoContext) {
    3414           6 :   v8::Isolate* isolate = CcTest::isolate();
    3415           6 :   v8::HandleScope scope(isolate);
    3416             : 
    3417           6 :   v8::Local<String> name = v8_str("my-symbol");
    3418           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3419           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3420           6 :   CHECK(glob2->SameValue(glob));
    3421             : 
    3422           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3423           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3424           6 :   CHECK(glob_api2->SameValue(glob_api));
    3425           6 :   CHECK(!glob_api->SameValue(glob));
    3426           6 : }
    3427             : 
    3428          60 : static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
    3429             :                                  const char* name) {
    3430          60 :   LocalContext env;
    3431          60 :   v8::Isolate* isolate = env->GetIsolate();
    3432         120 :   v8::HandleScope scope(isolate);
    3433             : 
    3434          60 :   v8::Local<v8::Symbol> symbol = getter(isolate);
    3435         120 :   std::string script = std::string("var sym = ") + name;
    3436             :   CompileRun(script.c_str());
    3437             :   v8::Local<Value> value =
    3438         300 :       env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
    3439             : 
    3440          60 :   CHECK(!value.IsEmpty());
    3441          60 :   CHECK(!symbol.IsEmpty());
    3442         120 :   CHECK(value->SameValue(symbol));
    3443          60 : }
    3444             : 
    3445             : 
    3446       23724 : THREADED_TEST(WellKnownSymbols) {
    3447           6 :   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
    3448           6 :   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
    3449           6 :   CheckWellKnownSymbol(v8::Symbol::GetHasInstance, "Symbol.hasInstance");
    3450             :   CheckWellKnownSymbol(v8::Symbol::GetIsConcatSpreadable,
    3451           6 :                        "Symbol.isConcatSpreadable");
    3452           6 :   CheckWellKnownSymbol(v8::Symbol::GetMatch, "Symbol.match");
    3453           6 :   CheckWellKnownSymbol(v8::Symbol::GetReplace, "Symbol.replace");
    3454           6 :   CheckWellKnownSymbol(v8::Symbol::GetSearch, "Symbol.search");
    3455           6 :   CheckWellKnownSymbol(v8::Symbol::GetSplit, "Symbol.split");
    3456           6 :   CheckWellKnownSymbol(v8::Symbol::GetToPrimitive, "Symbol.toPrimitive");
    3457           6 :   CheckWellKnownSymbol(v8::Symbol::GetToStringTag, "Symbol.toStringTag");
    3458           6 : }
    3459             : 
    3460             : 
    3461       23724 : THREADED_TEST(GlobalPrivates) {
    3462           6 :   i::FLAG_allow_natives_syntax = true;
    3463           6 :   LocalContext env;
    3464           6 :   v8::Isolate* isolate = env->GetIsolate();
    3465          12 :   v8::HandleScope scope(isolate);
    3466             : 
    3467           6 :   v8::Local<String> name = v8_str("my-private");
    3468           6 :   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
    3469           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3470          18 :   CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
    3471             :             .FromJust());
    3472             : 
    3473           6 :   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
    3474          12 :   CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
    3475             : 
    3476           6 :   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
    3477          12 :   CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
    3478             : 
    3479             :   CompileRun("var intern = %CreatePrivateSymbol('my-private')");
    3480             :   v8::Local<Value> intern =
    3481          30 :       env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
    3482          18 :   CHECK(!obj->Has(env.local(), intern).FromJust());
    3483           6 : }
    3484             : 
    3485             : 
    3486             : class ScopedArrayBufferContents {
    3487             :  public:
    3488             :   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
    3489          30 :       : contents_(contents) {}
    3490          30 :   ~ScopedArrayBufferContents() { free(contents_.AllocationBase()); }
    3491             :   void* Data() const { return contents_.Data(); }
    3492             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3493             : 
    3494             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3495             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3496             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3497             :     return contents_.AllocationMode();
    3498             :   }
    3499             : 
    3500             :  private:
    3501             :   const v8::ArrayBuffer::Contents contents_;
    3502             : };
    3503             : 
    3504             : template <typename T>
    3505         276 : static void CheckInternalFieldsAreZero(v8::Local<T> value) {
    3506         276 :   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
    3507         552 :   for (int i = 0; i < value->InternalFieldCount(); i++) {
    3508        1656 :     CHECK_EQ(0, value->GetInternalField(i)
    3509             :                     ->Int32Value(CcTest::isolate()->GetCurrentContext())
    3510             :                     .FromJust());
    3511             :   }
    3512         276 : }
    3513             : 
    3514             : 
    3515       23724 : THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
    3516           6 :   LocalContext env;
    3517           6 :   v8::Isolate* isolate = env->GetIsolate();
    3518          12 :   v8::HandleScope handle_scope(isolate);
    3519             : 
    3520           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
    3521           6 :   CheckInternalFieldsAreZero(ab);
    3522           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3523           6 :   CHECK(!ab->IsExternal());
    3524           6 :   CcTest::CollectAllGarbage();
    3525             : 
    3526          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3527           6 :   CHECK(ab->IsExternal());
    3528             : 
    3529           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3530             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3531           6 :   CHECK_NOT_NULL(data);
    3532          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3533             : 
    3534             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    3535          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3536             : 
    3537             :   result = CompileRun(
    3538             :       "var u8 = new Uint8Array(ab);"
    3539             :       "u8[0] = 0xFF;"
    3540             :       "u8[1] = 0xAA;"
    3541             :       "u8.length");
    3542          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3543          12 :   CHECK_EQ(0xFF, data[0]);
    3544          12 :   CHECK_EQ(0xAA, data[1]);
    3545           6 :   data[0] = 0xCC;
    3546           6 :   data[1] = 0x11;
    3547             :   result = CompileRun("u8[0] + u8[1]");
    3548          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3549           6 : }
    3550             : 
    3551             : 
    3552       23724 : THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
    3553           6 :   LocalContext env;
    3554           6 :   v8::Isolate* isolate = env->GetIsolate();
    3555          12 :   v8::HandleScope handle_scope(isolate);
    3556             : 
    3557             : 
    3558             :   v8::Local<v8::Value> result = CompileRun(
    3559             :       "var ab1 = new ArrayBuffer(2);"
    3560             :       "var u8_a = new Uint8Array(ab1);"
    3561             :       "u8_a[0] = 0xAA;"
    3562             :       "u8_a[1] = 0xFF; u8_a.buffer");
    3563             :   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
    3564           6 :   CheckInternalFieldsAreZero(ab1);
    3565           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    3566           6 :   CHECK(!ab1->IsExternal());
    3567          12 :   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
    3568           6 :   CHECK(ab1->IsExternal());
    3569             : 
    3570             :   result = CompileRun("ab1.byteLength");
    3571          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    3572             :   result = CompileRun("u8_a[0]");
    3573          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    3574             :   result = CompileRun("u8_a[1]");
    3575          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3576             :   result = CompileRun(
    3577             :       "var u8_b = new Uint8Array(ab1);"
    3578             :       "u8_b[0] = 0xBB;"
    3579             :       "u8_a[0]");
    3580          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    3581             :   result = CompileRun("u8_b[1]");
    3582          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3583             : 
    3584           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    3585             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    3586          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    3587          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    3588           6 :   ab1_data[0] = 0xCC;
    3589           6 :   ab1_data[1] = 0x11;
    3590             :   result = CompileRun("u8_a[0] + u8_a[1]");
    3591          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3592           6 : }
    3593             : 
    3594             : 
    3595       23724 : THREADED_TEST(ArrayBuffer_External) {
    3596           6 :   LocalContext env;
    3597           6 :   v8::Isolate* isolate = env->GetIsolate();
    3598          12 :   v8::HandleScope handle_scope(isolate);
    3599             : 
    3600             :   i::ScopedVector<uint8_t> my_data(100);
    3601             :   memset(my_data.start(), 0, 100);
    3602             :   Local<v8::ArrayBuffer> ab3 =
    3603           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3604           6 :   CheckInternalFieldsAreZero(ab3);
    3605           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    3606           6 :   CHECK(ab3->IsExternal());
    3607             : 
    3608          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    3609             : 
    3610             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    3611          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3612             : 
    3613             :   result = CompileRun(
    3614             :       "var u8_b = new Uint8Array(ab3);"
    3615             :       "u8_b[0] = 0xBB;"
    3616             :       "u8_b[1] = 0xCC;"
    3617             :       "u8_b.length");
    3618          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3619          12 :   CHECK_EQ(0xBB, my_data[0]);
    3620          12 :   CHECK_EQ(0xCC, my_data[1]);
    3621           6 :   my_data[0] = 0xCC;
    3622           6 :   my_data[1] = 0x11;
    3623             :   result = CompileRun("u8_b[0] + u8_b[1]");
    3624          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3625           6 : }
    3626             : 
    3627             : 
    3628       23724 : THREADED_TEST(ArrayBuffer_DisableNeuter) {
    3629           6 :   LocalContext env;
    3630           6 :   v8::Isolate* isolate = env->GetIsolate();
    3631          12 :   v8::HandleScope handle_scope(isolate);
    3632             : 
    3633             :   i::ScopedVector<uint8_t> my_data(100);
    3634             :   memset(my_data.start(), 0, 100);
    3635             :   Local<v8::ArrayBuffer> ab =
    3636           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3637           6 :   CHECK(ab->IsNeuterable());
    3638             : 
    3639             :   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
    3640             :   buf->set_is_neuterable(false);
    3641             : 
    3642          12 :   CHECK(!ab->IsNeuterable());
    3643           6 : }
    3644             : 
    3645             : 
    3646          12 : static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
    3647          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
    3648          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
    3649          12 : }
    3650             : 
    3651             : 
    3652         108 : static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
    3653         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
    3654         108 :   CHECK_EQ(0, static_cast<int>(ta->Length()));
    3655         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
    3656         108 : }
    3657             : 
    3658             : 
    3659          54 : static void CheckIsTypedArrayVarNeutered(const char* name) {
    3660             :   i::ScopedVector<char> source(1024);
    3661             :   i::SNPrintF(source,
    3662             :               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
    3663          54 :               name, name, name);
    3664          54 :   CHECK(CompileRun(source.start())->IsTrue());
    3665             :   v8::Local<v8::TypedArray> ta =
    3666          54 :       v8::Local<v8::TypedArray>::Cast(CompileRun(name));
    3667          54 :   CheckIsNeutered(ta);
    3668          54 : }
    3669             : 
    3670             : 
    3671             : template <typename TypedArray, int kElementSize>
    3672          54 : static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
    3673             :                                         int byteOffset, int length) {
    3674          54 :   v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
    3675          54 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
    3676          54 :   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
    3677          54 :   CHECK_EQ(length, static_cast<int>(ta->Length()));
    3678          54 :   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
    3679          54 :   return ta;
    3680             : }
    3681             : 
    3682             : 
    3683       23724 : THREADED_TEST(ArrayBuffer_NeuteringApi) {
    3684           6 :   LocalContext env;
    3685           6 :   v8::Isolate* isolate = env->GetIsolate();
    3686          12 :   v8::HandleScope handle_scope(isolate);
    3687             : 
    3688           6 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
    3689             : 
    3690             :   v8::Local<v8::Uint8Array> u8a =
    3691           6 :       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
    3692             :   v8::Local<v8::Uint8ClampedArray> u8c =
    3693           6 :       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
    3694             :   v8::Local<v8::Int8Array> i8a =
    3695           6 :       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
    3696             : 
    3697             :   v8::Local<v8::Uint16Array> u16a =
    3698           6 :       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
    3699             :   v8::Local<v8::Int16Array> i16a =
    3700           6 :       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
    3701             : 
    3702             :   v8::Local<v8::Uint32Array> u32a =
    3703           6 :       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
    3704             :   v8::Local<v8::Int32Array> i32a =
    3705           6 :       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
    3706             : 
    3707             :   v8::Local<v8::Float32Array> f32a =
    3708           6 :       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
    3709             :   v8::Local<v8::Float64Array> f64a =
    3710           6 :       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
    3711             : 
    3712           6 :   v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
    3713           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
    3714           6 :   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
    3715           6 :   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
    3716             : 
    3717          12 :   ScopedArrayBufferContents contents(buffer->Externalize());
    3718           6 :   buffer->Neuter();
    3719           6 :   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
    3720           6 :   CheckIsNeutered(u8a);
    3721           6 :   CheckIsNeutered(u8c);
    3722           6 :   CheckIsNeutered(i8a);
    3723           6 :   CheckIsNeutered(u16a);
    3724           6 :   CheckIsNeutered(i16a);
    3725           6 :   CheckIsNeutered(u32a);
    3726           6 :   CheckIsNeutered(i32a);
    3727           6 :   CheckIsNeutered(f32a);
    3728           6 :   CheckIsNeutered(f64a);
    3729          12 :   CheckDataViewIsNeutered(dv);
    3730           6 : }
    3731             : 
    3732             : 
    3733       23724 : THREADED_TEST(ArrayBuffer_NeuteringScript) {
    3734           6 :   LocalContext env;
    3735           6 :   v8::Isolate* isolate = env->GetIsolate();
    3736          12 :   v8::HandleScope handle_scope(isolate);
    3737             : 
    3738             :   CompileRun(
    3739             :       "var ab = new ArrayBuffer(1024);"
    3740             :       "var u8a = new Uint8Array(ab, 1, 1023);"
    3741             :       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
    3742             :       "var i8a = new Int8Array(ab, 1, 1023);"
    3743             :       "var u16a = new Uint16Array(ab, 2, 511);"
    3744             :       "var i16a = new Int16Array(ab, 2, 511);"
    3745             :       "var u32a = new Uint32Array(ab, 4, 255);"
    3746             :       "var i32a = new Int32Array(ab, 4, 255);"
    3747             :       "var f32a = new Float32Array(ab, 4, 255);"
    3748             :       "var f64a = new Float64Array(ab, 8, 127);"
    3749             :       "var dv = new DataView(ab, 1, 1023);");
    3750             : 
    3751             :   v8::Local<v8::ArrayBuffer> ab =
    3752             :       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
    3753             : 
    3754           6 :   v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
    3755             : 
    3756          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3757           6 :   ab->Neuter();
    3758           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3759           6 :   CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
    3760             : 
    3761           6 :   CheckIsTypedArrayVarNeutered("u8a");
    3762           6 :   CheckIsTypedArrayVarNeutered("u8c");
    3763           6 :   CheckIsTypedArrayVarNeutered("i8a");
    3764           6 :   CheckIsTypedArrayVarNeutered("u16a");
    3765           6 :   CheckIsTypedArrayVarNeutered("i16a");
    3766           6 :   CheckIsTypedArrayVarNeutered("u32a");
    3767           6 :   CheckIsTypedArrayVarNeutered("i32a");
    3768           6 :   CheckIsTypedArrayVarNeutered("f32a");
    3769           6 :   CheckIsTypedArrayVarNeutered("f64a");
    3770             : 
    3771           6 :   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
    3772          12 :   CheckDataViewIsNeutered(dv);
    3773           6 : }
    3774             : 
    3775       23724 : THREADED_TEST(ArrayBuffer_AllocationInformation) {
    3776           6 :   LocalContext env;
    3777           6 :   v8::Isolate* isolate = env->GetIsolate();
    3778          12 :   v8::HandleScope handle_scope(isolate);
    3779             : 
    3780             :   const size_t ab_size = 1024;
    3781           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, ab_size);
    3782          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3783             : 
    3784             :   // Array buffers should have normal allocation mode.
    3785           6 :   CHECK_EQ(contents.AllocationMode(),
    3786             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
    3787             :   // The allocation must contain the buffer (normally they will be equal, but
    3788             :   // this is not required by the contract).
    3789           6 :   CHECK_NOT_NULL(contents.AllocationBase());
    3790             :   const uintptr_t alloc =
    3791           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
    3792           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
    3793           6 :   CHECK_LE(alloc, data);
    3794          12 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
    3795           6 : }
    3796             : 
    3797             : class ScopedSharedArrayBufferContents {
    3798             :  public:
    3799             :   explicit ScopedSharedArrayBufferContents(
    3800             :       const v8::SharedArrayBuffer::Contents& contents)
    3801          18 :       : contents_(contents) {}
    3802          18 :   ~ScopedSharedArrayBufferContents() { free(contents_.AllocationBase()); }
    3803             :   void* Data() const { return contents_.Data(); }
    3804             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3805             : 
    3806             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3807             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3808             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3809             :     return contents_.AllocationMode();
    3810             :   }
    3811             : 
    3812             :  private:
    3813             :   const v8::SharedArrayBuffer::Contents contents_;
    3814             : };
    3815             : 
    3816             : 
    3817       23724 : THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
    3818           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    3819           6 :   LocalContext env;
    3820           6 :   v8::Isolate* isolate = env->GetIsolate();
    3821          12 :   v8::HandleScope handle_scope(isolate);
    3822             : 
    3823           6 :   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
    3824           6 :   CheckInternalFieldsAreZero(ab);
    3825           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3826           6 :   CHECK(!ab->IsExternal());
    3827           6 :   CcTest::CollectAllGarbage();
    3828             : 
    3829          12 :   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
    3830           6 :   CHECK(ab->IsExternal());
    3831             : 
    3832           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3833             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3834           6 :   CHECK_NOT_NULL(data);
    3835          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3836             : 
    3837             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    3838          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3839             : 
    3840             :   result = CompileRun(
    3841             :       "var u8 = new Uint8Array(ab);"
    3842             :       "u8[0] = 0xFF;"
    3843             :       "u8[1] = 0xAA;"
    3844             :       "u8.length");
    3845          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3846          12 :   CHECK_EQ(0xFF, data[0]);
    3847          12 :   CHECK_EQ(0xAA, data[1]);
    3848           6 :   data[0] = 0xCC;
    3849           6 :   data[1] = 0x11;
    3850             :   result = CompileRun("u8[0] + u8[1]");
    3851          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3852           6 : }
    3853             : 
    3854             : 
    3855       23724 : THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
    3856           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    3857           6 :   LocalContext env;
    3858           6 :   v8::Isolate* isolate = env->GetIsolate();
    3859          12 :   v8::HandleScope handle_scope(isolate);
    3860             : 
    3861             : 
    3862             :   v8::Local<v8::Value> result = CompileRun(
    3863             :       "var ab1 = new SharedArrayBuffer(2);"
    3864             :       "var u8_a = new Uint8Array(ab1);"
    3865             :       "u8_a[0] = 0xAA;"
    3866             :       "u8_a[1] = 0xFF; u8_a.buffer");
    3867             :   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
    3868           6 :   CheckInternalFieldsAreZero(ab1);
    3869           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    3870           6 :   CHECK(!ab1->IsExternal());
    3871          12 :   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
    3872           6 :   CHECK(ab1->IsExternal());
    3873             : 
    3874             :   result = CompileRun("ab1.byteLength");
    3875          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    3876             :   result = CompileRun("u8_a[0]");
    3877          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    3878             :   result = CompileRun("u8_a[1]");
    3879          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3880             :   result = CompileRun(
    3881             :       "var u8_b = new Uint8Array(ab1);"
    3882             :       "u8_b[0] = 0xBB;"
    3883             :       "u8_a[0]");
    3884          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    3885             :   result = CompileRun("u8_b[1]");
    3886          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3887             : 
    3888           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    3889             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    3890          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    3891          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    3892           6 :   ab1_data[0] = 0xCC;
    3893           6 :   ab1_data[1] = 0x11;
    3894             :   result = CompileRun("u8_a[0] + u8_a[1]");
    3895          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3896           6 : }
    3897             : 
    3898             : 
    3899       23724 : THREADED_TEST(SharedArrayBuffer_External) {
    3900           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    3901           6 :   LocalContext env;
    3902           6 :   v8::Isolate* isolate = env->GetIsolate();
    3903          12 :   v8::HandleScope handle_scope(isolate);
    3904             : 
    3905             :   i::ScopedVector<uint8_t> my_data(100);
    3906             :   memset(my_data.start(), 0, 100);
    3907             :   Local<v8::SharedArrayBuffer> ab3 =
    3908           6 :       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
    3909           6 :   CheckInternalFieldsAreZero(ab3);
    3910           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    3911           6 :   CHECK(ab3->IsExternal());
    3912             : 
    3913          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    3914             : 
    3915             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    3916          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3917             : 
    3918             :   result = CompileRun(
    3919             :       "var u8_b = new Uint8Array(ab3);"
    3920             :       "u8_b[0] = 0xBB;"
    3921             :       "u8_b[1] = 0xCC;"
    3922             :       "u8_b.length");
    3923          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3924          12 :   CHECK_EQ(0xBB, my_data[0]);
    3925          12 :   CHECK_EQ(0xCC, my_data[1]);
    3926           6 :   my_data[0] = 0xCC;
    3927           6 :   my_data[1] = 0x11;
    3928             :   result = CompileRun("u8_b[0] + u8_b[1]");
    3929          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3930           6 : }
    3931             : 
    3932             : 
    3933       23724 : THREADED_TEST(HiddenProperties) {
    3934           6 :   LocalContext env;
    3935           6 :   v8::Isolate* isolate = env->GetIsolate();
    3936          12 :   v8::HandleScope scope(isolate);
    3937             : 
    3938           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    3939             :   v8::Local<v8::Private> key =
    3940           6 :       v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
    3941           6 :   v8::Local<v8::String> empty = v8_str("");
    3942           6 :   v8::Local<v8::String> prop_name = v8_str("prop_name");
    3943             : 
    3944           6 :   CcTest::CollectAllGarbage();
    3945             : 
    3946             :   // Make sure delete of a non-existent hidden value works
    3947          12 :   obj->DeletePrivate(env.local(), key).FromJust();
    3948             : 
    3949          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
    3950             :             .FromJust());
    3951          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
    3952             :                      .ToLocalChecked()
    3953             :                      ->Int32Value(env.local())
    3954             :                      .FromJust());
    3955          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    3956             :             .FromJust());
    3957          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    3958             :                      .ToLocalChecked()
    3959             :                      ->Int32Value(env.local())
    3960             :                      .FromJust());
    3961             : 
    3962           6 :   CcTest::CollectAllGarbage();
    3963             : 
    3964             :   // Make sure we do not find the hidden property.
    3965          12 :   CHECK(!obj->Has(env.local(), empty).FromJust());
    3966          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    3967             :                      .ToLocalChecked()
    3968             :                      ->Int32Value(env.local())
    3969             :                      .FromJust());
    3970          12 :   CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
    3971          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    3972             :                      .ToLocalChecked()
    3973             :                      ->Int32Value(env.local())
    3974             :                      .FromJust());
    3975          18 :   CHECK(
    3976             :       obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
    3977          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    3978             :                      .ToLocalChecked()
    3979             :                      ->Int32Value(env.local())
    3980             :                      .FromJust());
    3981          24 :   CHECK_EQ(2003, obj->Get(env.local(), empty)
    3982             :                      .ToLocalChecked()
    3983             :                      ->Int32Value(env.local())
    3984             :                      .FromJust());
    3985             : 
    3986           6 :   CcTest::CollectAllGarbage();
    3987             : 
    3988             :   // Add another property and delete it afterwards to force the object in
    3989             :   // slow case.
    3990          18 :   CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
    3991             :             .FromJust());
    3992          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    3993             :                      .ToLocalChecked()
    3994             :                      ->Int32Value(env.local())
    3995             :                      .FromJust());
    3996          24 :   CHECK_EQ(2008, obj->Get(env.local(), prop_name)
    3997             :                      .ToLocalChecked()
    3998             :                      ->Int32Value(env.local())
    3999             :                      .FromJust());
    4000          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4001             :                      .ToLocalChecked()
    4002             :                      ->Int32Value(env.local())
    4003             :                      .FromJust());
    4004          12 :   CHECK(obj->Delete(env.local(), prop_name).FromJust());
    4005          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4006             :                      .ToLocalChecked()
    4007             :                      ->Int32Value(env.local())
    4008             :                      .FromJust());
    4009             : 
    4010           6 :   CcTest::CollectAllGarbage();
    4011             : 
    4012          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4013             :             .FromJust());
    4014          12 :   CHECK(obj->DeletePrivate(env.local(), key).FromJust());
    4015          18 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4016           6 : }
    4017             : 
    4018             : 
    4019       23724 : THREADED_TEST(Regress97784) {
    4020             :   // Regression test for crbug.com/97784
    4021             :   // Messing with the Object.prototype should not have effect on
    4022             :   // hidden properties.
    4023           6 :   LocalContext env;
    4024          12 :   v8::HandleScope scope(env->GetIsolate());
    4025             : 
    4026           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4027             :   v8::Local<v8::Private> key =
    4028          12 :       v8::Private::New(env->GetIsolate(), v8_str("hidden"));
    4029             : 
    4030             :   CompileRun(
    4031             :       "set_called = false;"
    4032             :       "Object.defineProperty("
    4033             :       "    Object.prototype,"
    4034             :       "    'hidden',"
    4035             :       "    {get: function() { return 45; },"
    4036             :       "     set: function() { set_called = true; }})");
    4037             : 
    4038          12 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4039             :   // Make sure that the getter and setter from Object.prototype is not invoked.
    4040             :   // If it did we would have full access to the hidden properties in
    4041             :   // the accessor.
    4042          18 :   CHECK(
    4043             :       obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
    4044             :           .FromJust());
    4045             :   ExpectFalse("set_called");
    4046          18 :   CHECK_EQ(42, obj->GetPrivate(env.local(), key)
    4047             :                    .ToLocalChecked()
    4048             :                    ->Int32Value(env.local())
    4049           6 :                    .FromJust());
    4050           6 : }
    4051             : 
    4052             : 
    4053       23724 : THREADED_TEST(External) {
    4054           6 :   v8::HandleScope scope(CcTest::isolate());
    4055           6 :   int x = 3;
    4056           6 :   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
    4057          12 :   LocalContext env;
    4058          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
    4059             :   Local<Value> reext_obj = CompileRun("this.ext");
    4060             :   v8::Local<v8::External> reext = reext_obj.As<v8::External>();
    4061           6 :   int* ptr = static_cast<int*>(reext->Value());
    4062           6 :   CHECK_EQ(3, x);
    4063           6 :   *ptr = 10;
    4064           6 :   CHECK_EQ(x, 10);
    4065             : 
    4066             :   {
    4067             :     i::Handle<i::Object> obj = v8::Utils::OpenHandle(*ext);
    4068          12 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4069           6 :     CHECK(ext->IsExternal());
    4070           6 :     CHECK(!CompileRun("new Set().add(this.ext)").IsEmpty());
    4071          12 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4072           6 :     CHECK(ext->IsExternal());
    4073             :   }
    4074             : 
    4075             :   // Make sure unaligned pointers are wrapped properly.
    4076           6 :   char* data = i::StrDup("0123456789");
    4077           6 :   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
    4078           6 :   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
    4079           6 :   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
    4080           6 :   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
    4081             : 
    4082           6 :   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
    4083           6 :   CHECK_EQ('0', *char_ptr);
    4084           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
    4085           6 :   CHECK_EQ('1', *char_ptr);
    4086           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
    4087           6 :   CHECK_EQ('2', *char_ptr);
    4088           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
    4089           6 :   CHECK_EQ('3', *char_ptr);
    4090           6 :   i::DeleteArray(data);
    4091           6 : }
    4092             : 
    4093             : 
    4094       23724 : THREADED_TEST(GlobalHandle) {
    4095           6 :   v8::Isolate* isolate = CcTest::isolate();
    4096             :   v8::Persistent<String> global;
    4097             :   {
    4098           6 :     v8::HandleScope scope(isolate);
    4099          12 :     global.Reset(isolate, v8_str("str"));
    4100             :   }
    4101             :   {
    4102           6 :     v8::HandleScope scope(isolate);
    4103           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4104             :   }
    4105             :   global.Reset();
    4106             :   {
    4107           6 :     v8::HandleScope scope(isolate);
    4108          12 :     global.Reset(isolate, v8_str("str"));
    4109             :   }
    4110             :   {
    4111           6 :     v8::HandleScope scope(isolate);
    4112           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4113             :   }
    4114             :   global.Reset();
    4115           6 : }
    4116             : 
    4117             : 
    4118       23724 : THREADED_TEST(ResettingGlobalHandle) {
    4119          12 :   v8::Isolate* isolate = CcTest::isolate();
    4120             :   v8::Persistent<String> global;
    4121             :   {
    4122           6 :     v8::HandleScope scope(isolate);
    4123          12 :     global.Reset(isolate, v8_str("str"));
    4124             :   }
    4125          18 :   v8::internal::GlobalHandles* global_handles =
    4126             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4127             :   int initial_handle_count = global_handles->global_handles_count();
    4128             :   {
    4129           6 :     v8::HandleScope scope(isolate);
    4130           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4131             :   }
    4132             :   {
    4133           6 :     v8::HandleScope scope(isolate);
    4134          12 :     global.Reset(isolate, v8_str("longer"));
    4135             :   }
    4136           6 :   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
    4137             :   {
    4138           6 :     v8::HandleScope scope(isolate);
    4139           6 :     CHECK_EQ(6, v8::Local<String>::New(isolate, global)->Length());
    4140             :   }
    4141             :   global.Reset();
    4142          12 :   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
    4143           6 : }
    4144             : 
    4145             : 
    4146       23724 : THREADED_TEST(ResettingGlobalHandleToEmpty) {
    4147          12 :   v8::Isolate* isolate = CcTest::isolate();
    4148             :   v8::Persistent<String> global;
    4149             :   {
    4150           6 :     v8::HandleScope scope(isolate);
    4151          12 :     global.Reset(isolate, v8_str("str"));
    4152             :   }
    4153          12 :   v8::internal::GlobalHandles* global_handles =
    4154             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4155             :   int initial_handle_count = global_handles->global_handles_count();
    4156             :   {
    4157           6 :     v8::HandleScope scope(isolate);
    4158           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4159             :   }
    4160             :   {
    4161           6 :     v8::HandleScope scope(isolate);
    4162             :     Local<String> empty;
    4163           6 :     global.Reset(isolate, empty);
    4164             :   }
    4165           6 :   CHECK(global.IsEmpty());
    4166          12 :   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
    4167           6 : }
    4168             : 
    4169             : 
    4170             : template <class T>
    4171             : static v8::Global<T> PassUnique(v8::Global<T> unique) {
    4172             :   return unique.Pass();
    4173             : }
    4174             : 
    4175             : 
    4176             : template <class T>
    4177             : static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
    4178             :                                   const v8::Persistent<T>& global) {
    4179             :   v8::Global<String> unique(isolate, global);
    4180             :   return unique.Pass();
    4181             : }
    4182             : 
    4183             : 
    4184       23724 : THREADED_TEST(Global) {
    4185          12 :   v8::Isolate* isolate = CcTest::isolate();
    4186             :   v8::Persistent<String> global;
    4187             :   {
    4188           6 :     v8::HandleScope scope(isolate);
    4189          12 :     global.Reset(isolate, v8_str("str"));
    4190             :   }
    4191          42 :   v8::internal::GlobalHandles* global_handles =
    4192             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4193             :   int initial_handle_count = global_handles->global_handles_count();
    4194             :   {
    4195             :     v8::Global<String> unique(isolate, global);
    4196           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4197             :     // Test assignment via Pass
    4198             :     {
    4199             :       v8::Global<String> copy = unique.Pass();
    4200           6 :       CHECK(unique.IsEmpty());
    4201           6 :       CHECK(copy == global);
    4202           6 :       CHECK_EQ(initial_handle_count + 1,
    4203             :                global_handles->global_handles_count());
    4204             :       unique = copy.Pass();
    4205             :     }
    4206             :     // Test ctor via Pass
    4207             :     {
    4208             :       v8::Global<String> copy(unique.Pass());
    4209           6 :       CHECK(unique.IsEmpty());
    4210           6 :       CHECK(copy == global);
    4211           6 :       CHECK_EQ(initial_handle_count + 1,
    4212             :                global_handles->global_handles_count());
    4213             :       unique = copy.Pass();
    4214             :     }
    4215             :     // Test pass through function call
    4216             :     {
    4217             :       v8::Global<String> copy = PassUnique(unique.Pass());
    4218           6 :       CHECK(unique.IsEmpty());
    4219           6 :       CHECK(copy == global);
    4220           6 :       CHECK_EQ(initial_handle_count + 1,
    4221             :                global_handles->global_handles_count());
    4222             :       unique = copy.Pass();
    4223             :     }
    4224           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4225             :   }
    4226             :   // Test pass from function call
    4227             :   {
    4228             :     v8::Global<String> unique = ReturnUnique(isolate, global);
    4229           6 :     CHECK(unique == global);
    4230           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4231             :   }
    4232           6 :   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
    4233             :   global.Reset();
    4234           6 : }
    4235             : 
    4236             : 
    4237             : namespace {
    4238             : 
    4239             : class TwoPassCallbackData;
    4240             : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4241             : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4242             : 
    4243             : 
    4244             : class TwoPassCallbackData {
    4245             :  public:
    4246         215 :   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
    4247             :       : first_pass_called_(false),
    4248             :         second_pass_called_(false),
    4249             :         trigger_gc_(false),
    4250         430 :         instance_counter_(instance_counter) {
    4251         215 :     HandleScope scope(isolate);
    4252             :     i::ScopedVector<char> buffer(40);
    4253         215 :     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
    4254             :     auto string =
    4255             :         v8::String::NewFromUtf8(isolate, buffer.start(),
    4256         215 :                                 v8::NewStringType::kNormal).ToLocalChecked();
    4257             :     cell_.Reset(isolate, string);
    4258         430 :     (*instance_counter_)++;
    4259         215 :   }
    4260             : 
    4261         215 :   ~TwoPassCallbackData() {
    4262         215 :     CHECK(first_pass_called_);
    4263         215 :     CHECK(second_pass_called_);
    4264         215 :     CHECK(cell_.IsEmpty());
    4265         215 :     (*instance_counter_)--;
    4266         215 :   }
    4267             : 
    4268         215 :   void FirstPass() {
    4269         215 :     CHECK(!first_pass_called_);
    4270         215 :     CHECK(!second_pass_called_);
    4271         215 :     CHECK(!cell_.IsEmpty());
    4272             :     cell_.Reset();
    4273         215 :     first_pass_called_ = true;
    4274         215 :   }
    4275             : 
    4276         215 :   void SecondPass() {
    4277         215 :     CHECK(first_pass_called_);
    4278         215 :     CHECK(!second_pass_called_);
    4279         215 :     CHECK(cell_.IsEmpty());
    4280         215 :     second_pass_called_ = true;
    4281         215 :     delete this;
    4282         215 :   }
    4283             : 
    4284             :   void SetWeak() {
    4285             :     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
    4286             :   }
    4287             : 
    4288          15 :   void MarkTriggerGc() { trigger_gc_ = true; }
    4289             :   bool trigger_gc() { return trigger_gc_; }
    4290             : 
    4291             :   int* instance_counter() { return instance_counter_; }
    4292             : 
    4293             :  private:
    4294             :   bool first_pass_called_;
    4295             :   bool second_pass_called_;
    4296             :   bool trigger_gc_;
    4297             :   v8::Global<v8::String> cell_;
    4298             :   int* instance_counter_;
    4299             : };
    4300             : 
    4301             : 
    4302         445 : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4303         215 :   ApiTestFuzzer::Fuzz();
    4304         215 :   bool trigger_gc = data.GetParameter()->trigger_gc();
    4305         215 :   int* instance_counter = data.GetParameter()->instance_counter();
    4306         215 :   data.GetParameter()->SecondPass();
    4307         430 :   if (!trigger_gc) return;
    4308          15 :   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
    4309             :   data_2->SetWeak();
    4310          15 :   CcTest::CollectAllGarbage();
    4311             : }
    4312             : 
    4313             : 
    4314         430 : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4315         215 :   data.GetParameter()->FirstPass();
    4316             :   data.SetSecondPassCallback(SecondPassCallback);
    4317         215 : }
    4318             : 
    4319             : }  // namespace
    4320             : 
    4321             : 
    4322       23723 : TEST(TwoPassPhantomCallbacks) {
    4323           5 :   auto isolate = CcTest::isolate();
    4324             :   const size_t kLength = 20;
    4325           5 :   int instance_counter = 0;
    4326         105 :   for (size_t i = 0; i < kLength; ++i) {
    4327         100 :     auto data = new TwoPassCallbackData(isolate, &instance_counter);
    4328             :     data->SetWeak();
    4329             :   }
    4330           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4331           5 :   CcTest::CollectAllGarbage();
    4332           5 :   EmptyMessageQueues(isolate);
    4333           5 :   CHECK_EQ(0, instance_counter);
    4334           5 : }
    4335             : 
    4336             : 
    4337       23723 : TEST(TwoPassPhantomCallbacksNestedGc) {
    4338           5 :   auto isolate = CcTest::isolate();
    4339             :   const size_t kLength = 20;
    4340             :   TwoPassCallbackData* array[kLength];
    4341           5 :   int instance_counter = 0;
    4342         105 :   for (size_t i = 0; i < kLength; ++i) {
    4343         100 :     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
    4344             :     array[i]->SetWeak();
    4345             :   }
    4346           5 :   array[5]->MarkTriggerGc();
    4347           5 :   array[10]->MarkTriggerGc();
    4348           5 :   array[15]->MarkTriggerGc();
    4349           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4350           5 :   CcTest::CollectAllGarbage();
    4351           5 :   EmptyMessageQueues(isolate);
    4352           5 :   CHECK_EQ(0, instance_counter);
    4353           5 : }
    4354             : 
    4355             : 
    4356             : namespace {
    4357             : 
    4358          30 : void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
    4359             : 
    4360             : 
    4361          20 : Local<v8::Object> NewObjectForIntKey(
    4362             :     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
    4363             :     int key) {
    4364             :   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
    4365          20 :   auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
    4366          20 :   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
    4367          20 :   return obj;
    4368             : }
    4369             : 
    4370             : 
    4371             : template <typename K, typename V>
    4372             : class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
    4373             :  public:
    4374             :   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
    4375             :   static const v8::PersistentContainerCallbackType kCallbackType =
    4376             :       v8::kWeakWithInternalFields;
    4377             :   struct WeakCallbackDataType {
    4378             :     MapType* map;
    4379             :     K key;
    4380             :   };
    4381             :   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
    4382             :                                                      Local<V> value) {
    4383          25 :     WeakCallbackDataType* data = new WeakCallbackDataType;
    4384          25 :     data->map = map;
    4385          25 :     data->key = key;
    4386             :     return data;
    4387             :   }
    4388             :   static MapType* MapFromWeakCallbackInfo(
    4389           5 :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4390           5 :     return data.GetParameter()->map;
    4391             :   }
    4392             :   static K KeyFromWeakCallbackInfo(
    4393           5 :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4394          10 :     return data.GetParameter()->key;
    4395             :   }
    4396          25 :   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
    4397           5 :   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
    4398           5 :     CHECK_EQ(IntKeyToVoidPointer(key),
    4399             :              v8::Object::GetAlignedPointerFromInternalField(value, 0));
    4400           5 :   }
    4401             :   static void OnWeakCallback(
    4402             :       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
    4403           5 :   static void DisposeWeak(
    4404             :       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
    4405             :     K key = KeyFromWeakCallbackInfo(info);
    4406           5 :     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
    4407             :     DisposeCallbackData(info.GetParameter());
    4408           5 :   }
    4409             : };
    4410             : 
    4411             : 
    4412             : template <typename Map>
    4413          10 : void TestGlobalValueMap() {
    4414          10 :   LocalContext env;
    4415          20 :   v8::Isolate* isolate = env->GetIsolate();
    4416             :   v8::Global<ObjectTemplate> templ;
    4417             :   {
    4418          10 :     HandleScope scope(isolate);
    4419          10 :     auto t = ObjectTemplate::New(isolate);
    4420          10 :     t->SetInternalFieldCount(1);
    4421          10 :     templ.Reset(isolate, t);
    4422             :   }
    4423             :   Map map(isolate);
    4424          40 :   v8::internal::GlobalHandles* global_handles =
    4425             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4426             :   int initial_handle_count = global_handles->global_handles_count();
    4427          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4428             :   {
    4429          10 :     HandleScope scope(isolate);
    4430          10 :     Local<v8::Object> obj = map.Get(7);
    4431          10 :     CHECK(obj.IsEmpty());
    4432          10 :     Local<v8::Object> expected = v8::Object::New(isolate);
    4433          20 :     map.Set(7, expected);
    4434          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4435          10 :     obj = map.Get(7);
    4436          20 :     CHECK(expected->Equals(env.local(), obj).FromJust());
    4437             :     {
    4438          10 :       typename Map::PersistentValueReference ref = map.GetReference(7);
    4439          20 :       CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4440             :     }
    4441           5 :     v8::Global<v8::Object> removed = map.Remove(7);
    4442          10 :     CHECK_EQ(0, static_cast<int>(map.Size()));
    4443          10 :     CHECK(expected == removed);
    4444          10 :     removed = map.Remove(7);
    4445          10 :     CHECK(removed.IsEmpty());
    4446          20 :     map.Set(8, expected);
    4447          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4448          20 :     map.Set(8, expected);
    4449          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4450             :     {
    4451             :       typename Map::PersistentValueReference ref;
    4452          10 :       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
    4453          15 :       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
    4454          10 :       CHECK_EQ(1, static_cast<int>(map.Size()));
    4455          10 :       CHECK(expected == removed);
    4456          20 :       CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4457          10 :     }
    4458             :   }
    4459          10 :   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4460             :   if (map.IsWeak()) {
    4461           5 :     CcTest::CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
    4462             :   } else {
    4463           5 :     map.Clear();
    4464             :   }
    4465          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4466          10 :   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
    4467             :   {
    4468          10 :     HandleScope scope(isolate);
    4469          10 :     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
    4470          20 :     map.Set(9, value);
    4471          10 :     map.Clear();
    4472             :   }
    4473          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4474          20 :   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
    4475          10 : }
    4476             : 
    4477             : }  // namespace
    4478             : 
    4479             : 
    4480       23723 : TEST(GlobalValueMap) {
    4481             :   // Default case, w/o weak callbacks:
    4482           5 :   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
    4483             : 
    4484             :   // Custom traits with weak callbacks:
    4485             :   typedef v8::GlobalValueMap<int, v8::Object,
    4486             :                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
    4487           5 :   TestGlobalValueMap<WeakMap>();
    4488           5 : }
    4489             : 
    4490             : 
    4491       23723 : TEST(PersistentValueVector) {
    4492           5 :   LocalContext env;
    4493           5 :   v8::Isolate* isolate = env->GetIsolate();
    4494          15 :   v8::internal::GlobalHandles* global_handles =
    4495             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4496             :   int handle_count = global_handles->global_handles_count();
    4497          10 :   HandleScope scope(isolate);
    4498             : 
    4499           5 :   v8::PersistentValueVector<v8::Object> vector(isolate);
    4500             : 
    4501           5 :   Local<v8::Object> obj1 = v8::Object::New(isolate);
    4502           5 :   Local<v8::Object> obj2 = v8::Object::New(isolate);
    4503           5 :   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
    4504             : 
    4505           5 :   CHECK(vector.IsEmpty());
    4506           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4507             : 
    4508             :   vector.ReserveCapacity(3);
    4509           5 :   CHECK(vector.IsEmpty());
    4510             : 
    4511           5 :   vector.Append(obj1);
    4512           5 :   vector.Append(obj2);
    4513           5 :   vector.Append(obj1);
    4514             :   vector.Append(obj3.Pass());
    4515           5 :   vector.Append(obj1);
    4516             : 
    4517           5 :   CHECK(!vector.IsEmpty());
    4518           5 :   CHECK_EQ(5, static_cast<int>(vector.Size()));
    4519           5 :   CHECK(obj3.IsEmpty());
    4520          15 :   CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
    4521          15 :   CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
    4522          15 :   CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
    4523          20 :   CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
    4524             : 
    4525           5 :   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
    4526             : 
    4527           5 :   vector.Clear();
    4528           5 :   CHECK(vector.IsEmpty());
    4529           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4530          10 :   CHECK_EQ(handle_count, global_handles->global_handles_count());
    4531           5 : }
    4532             : 
    4533             : 
    4534       23724 : THREADED_TEST(GlobalHandleUpcast) {
    4535           6 :   v8::Isolate* isolate = CcTest::isolate();
    4536           6 :   v8::HandleScope scope(isolate);
    4537           6 :   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
    4538             :   v8::Persistent<String> global_string(isolate, local);
    4539             :   v8::Persistent<Value>& global_value =
    4540             :       v8::Persistent<Value>::Cast(global_string);
    4541           6 :   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
    4542           6 :   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
    4543           6 :   global_string.Reset();
    4544           6 : }
    4545             : 
    4546             : 
    4547       23724 : THREADED_TEST(HandleEquality) {
    4548           6 :   v8::Isolate* isolate = CcTest::isolate();
    4549             :   v8::Persistent<String> global1;
    4550             :   v8::Persistent<String> global2;
    4551             :   {
    4552           6 :     v8::HandleScope scope(isolate);
    4553          12 :     global1.Reset(isolate, v8_str("str"));
    4554          12 :     global2.Reset(isolate, v8_str("str2"));
    4555             :   }
    4556           6 :   CHECK(global1 == global1);
    4557           6 :   CHECK(!(global1 != global1));
    4558             :   {
    4559           6 :     v8::HandleScope scope(isolate);
    4560             :     Local<String> local1 = Local<String>::New(isolate, global1);
    4561             :     Local<String> local2 = Local<String>::New(isolate, global2);
    4562             : 
    4563           6 :     CHECK(global1 == local1);
    4564           6 :     CHECK(!(global1 != local1));
    4565           6 :     CHECK(local1 == global1);
    4566           6 :     CHECK(!(local1 != global1));
    4567             : 
    4568           6 :     CHECK(!(global1 == local2));
    4569           6 :     CHECK(global1 != local2);
    4570           6 :     CHECK(!(local2 == global1));
    4571           6 :     CHECK(local2 != global1);
    4572             : 
    4573           6 :     CHECK(!(local1 == local2));
    4574           6 :     CHECK(local1 != local2);
    4575             : 
    4576             :     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
    4577           6 :     CHECK(local1 == anotherLocal1);
    4578           6 :     CHECK(!(local1 != anotherLocal1));
    4579             :   }
    4580             :   global1.Reset();
    4581             :   global2.Reset();
    4582           6 : }
    4583             : 
    4584             : 
    4585       23724 : THREADED_TEST(LocalHandle) {
    4586           6 :   v8::HandleScope scope(CcTest::isolate());
    4587             :   v8::Local<String> local =
    4588           6 :       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
    4589           6 :   CHECK_EQ(3, local->Length());
    4590           6 : }
    4591             : 
    4592             : 
    4593             : class WeakCallCounter {
    4594             :  public:
    4595          10 :   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
    4596             :   int id() { return id_; }
    4597          25 :   void increment() { number_of_weak_calls_++; }
    4598             :   int NumberOfWeakCalls() { return number_of_weak_calls_; }
    4599             : 
    4600             :  private:
    4601             :   int id_;
    4602             :   int number_of_weak_calls_;
    4603             : };
    4604             : 
    4605             : 
    4606             : template <typename T>
    4607             : struct WeakCallCounterAndPersistent {
    4608             :   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
    4609          25 :       : counter(counter) {}
    4610             :   WeakCallCounter* counter;
    4611             :   v8::Persistent<T> handle;
    4612             : };
    4613             : 
    4614             : 
    4615             : template <typename T>
    4616          25 : static void WeakPointerCallback(
    4617          50 :     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
    4618          25 :   CHECK_EQ(1234, data.GetParameter()->counter->id());
    4619             :   data.GetParameter()->counter->increment();
    4620             :   data.GetParameter()->handle.Reset();
    4621          25 : }
    4622             : 
    4623       23724 : THREADED_TEST(ScriptException) {
    4624           6 :   LocalContext env;
    4625          12 :   v8::HandleScope scope(env->GetIsolate());
    4626             :   Local<Script> script = v8_compile("throw 'panama!';");
    4627          12 :   v8::TryCatch try_catch(env->GetIsolate());
    4628           6 :   v8::MaybeLocal<Value> result = script->Run(env.local());
    4629           6 :   CHECK(result.IsEmpty());
    4630           6 :   CHECK(try_catch.HasCaught());
    4631          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    4632          12 :   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
    4633           6 : }
    4634             : 
    4635             : 
    4636       23723 : TEST(TryCatchCustomException) {
    4637           5 :   LocalContext env;
    4638           5 :   v8::Isolate* isolate = env->GetIsolate();
    4639          10 :   v8::HandleScope scope(isolate);
    4640          10 :   v8::TryCatch try_catch(isolate);
    4641             :   CompileRun(
    4642             :       "function CustomError() { this.a = 'b'; }"
    4643             :       "(function f() { throw new CustomError(); })();");
    4644           5 :   CHECK(try_catch.HasCaught());
    4645          35 :   CHECK(try_catch.Exception()
    4646             :             ->ToObject(env.local())
    4647             :             .ToLocalChecked()
    4648             :             ->Get(env.local(), v8_str("a"))
    4649             :             .ToLocalChecked()
    4650             :             ->Equals(env.local(), v8_str("b"))
    4651           5 :             .FromJust());
    4652           5 : }
    4653             : 
    4654             : 
    4655             : bool message_received;
    4656             : 
    4657             : 
    4658           6 : static void check_message_0(v8::Local<v8::Message> message,
    4659             :                             v8::Local<Value> data) {
    4660          18 :   CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
    4661             :                      .FromJust());
    4662          12 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4663             :                      .ResourceName()
    4664             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4665             :                      .FromJust());
    4666           6 :   CHECK(!message->IsSharedCrossOrigin());
    4667           6 :   message_received = true;
    4668           6 : }
    4669             : 
    4670             : 
    4671       23724 : THREADED_TEST(MessageHandler0) {
    4672           6 :   message_received = false;
    4673           6 :   v8::HandleScope scope(CcTest::isolate());
    4674           6 :   CHECK(!message_received);
    4675          12 :   LocalContext context;
    4676           6 :   CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
    4677           6 :   v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
    4678          18 :   CHECK(script->Run(context.local()).IsEmpty());
    4679           6 :   CHECK(message_received);
    4680             :   // clear out the message listener
    4681          12 :   CcTest::isolate()->RemoveMessageListeners(check_message_0);
    4682           6 : }
    4683             : 
    4684             : 
    4685           5 : static void check_message_1(v8::Local<v8::Message> message,
    4686             :                             v8::Local<Value> data) {
    4687           5 :   CHECK(data->IsNumber());
    4688          10 :   CHECK_EQ(1337,
    4689             :            data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
    4690           5 :   CHECK(!message->IsSharedCrossOrigin());
    4691           5 :   message_received = true;
    4692           5 : }
    4693             : 
    4694             : 
    4695       23723 : TEST(MessageHandler1) {
    4696           5 :   message_received = false;
    4697           5 :   v8::HandleScope scope(CcTest::isolate());
    4698           5 :   CHECK(!message_received);
    4699           5 :   CcTest::isolate()->AddMessageListener(check_message_1);
    4700          10 :   LocalContext context;
    4701             :   CompileRun("throw 1337;");
    4702           5 :   CHECK(message_received);
    4703             :   // clear out the message listener
    4704          10 :   CcTest::isolate()->RemoveMessageListeners(check_message_1);
    4705           5 : }
    4706             : 
    4707             : 
    4708           5 : static void check_message_2(v8::Local<v8::Message> message,
    4709             :                             v8::Local<Value> data) {
    4710           5 :   LocalContext context;
    4711           5 :   CHECK(data->IsObject());
    4712             :   v8::Local<v8::Value> hidden_property =
    4713             :       v8::Object::Cast(*data)
    4714             :           ->GetPrivate(
    4715             :               context.local(),
    4716           5 :               v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
    4717          10 :           .ToLocalChecked();
    4718          15 :   CHECK(v8_str("hidden value")
    4719             :             ->Equals(context.local(), hidden_property)
    4720             :             .FromJust());
    4721           5 :   CHECK(!message->IsSharedCrossOrigin());
    4722           5 :   message_received = true;
    4723           5 : }
    4724             : 
    4725             : 
    4726       23723 : TEST(MessageHandler2) {
    4727           5 :   message_received = false;
    4728           5 :   v8::HandleScope scope(CcTest::isolate());
    4729           5 :   CHECK(!message_received);
    4730           5 :   CcTest::isolate()->AddMessageListener(check_message_2);
    4731          10 :   LocalContext context;
    4732           5 :   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
    4733             :   v8::Object::Cast(*error)
    4734             :       ->SetPrivate(context.local(),
    4735             :                    v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
    4736          15 :                    v8_str("hidden value"))
    4737          10 :       .FromJust();
    4738          25 :   CHECK(context->Global()
    4739             :             ->Set(context.local(), v8_str("error"), error)
    4740             :             .FromJust());
    4741             :   CompileRun("throw error;");
    4742           5 :   CHECK(message_received);
    4743             :   // clear out the message listener
    4744          10 :   CcTest::isolate()->RemoveMessageListeners(check_message_2);
    4745           5 : }
    4746             : 
    4747             : 
    4748           5 : static void check_message_3(v8::Local<v8::Message> message,
    4749             :                             v8::Local<Value> data) {
    4750           5 :   CHECK(message->IsSharedCrossOrigin());
    4751          10 :   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
    4752          10 :   CHECK(message->GetScriptOrigin().Options().IsOpaque());
    4753          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4754             :                      .ResourceName()
    4755             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4756             :                      .FromJust());
    4757          10 :   CHECK_EQ(7.40, message->GetScriptOrigin()
    4758             :                      .SourceMapUrl()
    4759             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4760             :                      .FromJust());
    4761           5 :   message_received = true;
    4762           5 : }
    4763             : 
    4764             : 
    4765       23723 : TEST(MessageHandler3) {
    4766           5 :   message_received = false;
    4767           5 :   v8::Isolate* isolate = CcTest::isolate();
    4768           5 :   v8::HandleScope scope(isolate);
    4769           5 :   CHECK(!message_received);
    4770           5 :   isolate->AddMessageListener(check_message_3);
    4771          10 :   LocalContext context;
    4772             :   v8::ScriptOrigin origin =
    4773             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4774             :                        v8::Integer::New(isolate, 2), v8::True(isolate),
    4775           5 :                        Local<v8::Integer>(), v8_str("7.40"), v8::True(isolate));
    4776             :   v8::Local<v8::Script> script =
    4777           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4778           5 :           .ToLocalChecked();
    4779          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4780           5 :   CHECK(message_received);
    4781             :   // clear out the message listener
    4782          10 :   isolate->RemoveMessageListeners(check_message_3);
    4783           5 : }
    4784             : 
    4785             : 
    4786           5 : static void check_message_4(v8::Local<v8::Message> message,
    4787             :                             v8::Local<Value> data) {
    4788           5 :   CHECK(!message->IsSharedCrossOrigin());
    4789          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4790             :                      .ResourceName()
    4791             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4792             :                      .FromJust());
    4793           5 :   message_received = true;
    4794           5 : }
    4795             : 
    4796             : 
    4797       23723 : TEST(MessageHandler4) {
    4798           5 :   message_received = false;
    4799           5 :   v8::Isolate* isolate = CcTest::isolate();
    4800           5 :   v8::HandleScope scope(isolate);
    4801           5 :   CHECK(!message_received);
    4802           5 :   isolate->AddMessageListener(check_message_4);
    4803          10 :   LocalContext context;
    4804             :   v8::ScriptOrigin origin =
    4805             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4806           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    4807             :   v8::Local<v8::Script> script =
    4808           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4809           5 :           .ToLocalChecked();
    4810          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4811           5 :   CHECK(message_received);
    4812             :   // clear out the message listener
    4813          10 :   isolate->RemoveMessageListeners(check_message_4);
    4814           5 : }
    4815             : 
    4816             : 
    4817           5 : static void check_message_5a(v8::Local<v8::Message> message,
    4818             :                              v8::Local<Value> data) {
    4819           5 :   CHECK(message->IsSharedCrossOrigin());
    4820          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4821             :                      .ResourceName()
    4822             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4823             :                      .FromJust());
    4824           5 :   message_received = true;
    4825           5 : }
    4826             : 
    4827             : 
    4828           5 : static void check_message_5b(v8::Local<v8::Message> message,
    4829             :                              v8::Local<Value> data) {
    4830           5 :   CHECK(!message->IsSharedCrossOrigin());
    4831          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4832             :                      .ResourceName()
    4833             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4834             :                      .FromJust());
    4835           5 :   message_received = true;
    4836           5 : }
    4837             : 
    4838             : 
    4839       23723 : TEST(MessageHandler5) {
    4840           5 :   message_received = false;
    4841           5 :   v8::Isolate* isolate = CcTest::isolate();
    4842           5 :   v8::HandleScope scope(isolate);
    4843           5 :   CHECK(!message_received);
    4844           5 :   isolate->AddMessageListener(check_message_5a);
    4845          10 :   LocalContext context;
    4846             :   v8::ScriptOrigin origin1 =
    4847             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4848           5 :                        v8::Integer::New(isolate, 2), v8::True(isolate));
    4849             :   v8::Local<v8::Script> script =
    4850           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
    4851           5 :           .ToLocalChecked();
    4852          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4853           5 :   CHECK(message_received);
    4854             :   // clear out the message listener
    4855           5 :   isolate->RemoveMessageListeners(check_message_5a);
    4856             : 
    4857           5 :   message_received = false;
    4858           5 :   isolate->AddMessageListener(check_message_5b);
    4859             :   v8::ScriptOrigin origin2 =
    4860             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4861           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    4862           5 :   script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
    4863           5 :                .ToLocalChecked();
    4864          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4865           5 :   CHECK(message_received);
    4866             :   // clear out the message listener
    4867          10 :   isolate->RemoveMessageListeners(check_message_5b);
    4868           5 : }
    4869             : 
    4870             : 
    4871       23723 : TEST(NativeWeakMap) {
    4872           5 :   v8::Isolate* isolate = CcTest::isolate();
    4873           5 :   HandleScope scope(isolate);
    4874           5 :   Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
    4875           5 :   CHECK(!weak_map.IsEmpty());
    4876             : 
    4877          10 :   LocalContext env;
    4878           5 :   Local<Object> value = v8::Object::New(isolate);
    4879             : 
    4880           5 :   Local<Object> local1 = v8::Object::New(isolate);
    4881           5 :   CHECK(!weak_map->Has(local1));
    4882          10 :   CHECK(weak_map->Get(local1)->IsUndefined());
    4883           5 :   weak_map->Set(local1, value);
    4884           5 :   CHECK(weak_map->Has(local1));
    4885          10 :   CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
    4886             : 
    4887             :   WeakCallCounter counter(1234);
    4888             :   WeakCallCounterAndPersistent<Value> o1(&counter);
    4889             :   WeakCallCounterAndPersistent<Value> o2(&counter);
    4890             :   WeakCallCounterAndPersistent<Value> s1(&counter);
    4891             :   {
    4892           5 :     HandleScope scope(isolate);
    4893           5 :     Local<v8::Object> obj1 = v8::Object::New(isolate);
    4894           5 :     Local<v8::Object> obj2 = v8::Object::New(isolate);
    4895           5 :     Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
    4896             : 
    4897           5 :     weak_map->Set(obj1, value);
    4898           5 :     weak_map->Set(obj2, value);
    4899           5 :     weak_map->Set(sym1, value);
    4900             : 
    4901             :     o1.handle.Reset(isolate, obj1);
    4902             :     o2.handle.Reset(isolate, obj2);
    4903             :     s1.handle.Reset(isolate, sym1);
    4904             : 
    4905           5 :     CHECK(weak_map->Has(local1));
    4906           5 :     CHECK(weak_map->Has(obj1));
    4907           5 :     CHECK(weak_map->Has(obj2));
    4908           5 :     CHECK(weak_map->Has(sym1));
    4909             : 
    4910          10 :     CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
    4911          10 :     CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
    4912          10 :     CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
    4913          10 :     CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
    4914             :   }
    4915           5 :   CcTest::CollectAllGarbage();
    4916             :   {
    4917           5 :     HandleScope scope(isolate);
    4918          10 :     CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
    4919          10 :     CHECK(value->Equals(env.local(),
    4920             :                         weak_map->Get(Local<Value>::New(isolate, o1.handle)))
    4921             :               .FromJust());
    4922          10 :     CHECK(value->Equals(env.local(),
    4923             :                         weak_map->Get(Local<Value>::New(isolate, o2.handle)))
    4924             :               .FromJust());
    4925          10 :     CHECK(value->Equals(env.local(),
    4926             :                         weak_map->Get(Local<Value>::New(isolate, s1.handle)))
    4927           5 :               .FromJust());
    4928             :   }
    4929             : 
    4930             :   o1.handle.SetWeak(&o1, &WeakPointerCallback,
    4931             :                     v8::WeakCallbackType::kParameter);
    4932             :   o2.handle.SetWeak(&o2, &WeakPointerCallback,
    4933             :                     v8::WeakCallbackType::kParameter);
    4934             :   s1.handle.SetWeak(&s1, &WeakPointerCallback,
    4935             :                     v8::WeakCallbackType::kParameter);
    4936             : 
    4937           5 :   CcTest::CollectAllGarbage();
    4938           5 :   CHECK_EQ(3, counter.NumberOfWeakCalls());
    4939             : 
    4940           5 :   CHECK(o1.handle.IsEmpty());
    4941           5 :   CHECK(o2.handle.IsEmpty());
    4942           5 :   CHECK(s1.handle.IsEmpty());
    4943             : 
    4944          10 :   CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
    4945           5 :   CHECK(weak_map->Delete(local1));
    4946           5 :   CHECK(!weak_map->Has(local1));
    4947          15 :   CHECK(weak_map->Get(local1)->IsUndefined());
    4948           5 : }
    4949             : 
    4950             : 
    4951       23724 : THREADED_TEST(GetSetProperty) {
    4952           6 :   LocalContext context;
    4953           6 :   v8::Isolate* isolate = context->GetIsolate();
    4954          12 :   v8::HandleScope scope(isolate);
    4955          30 :   CHECK(context->Global()
    4956             :             ->Set(context.local(), v8_str("foo"), v8_num(14))
    4957             :             .FromJust());
    4958          30 :   CHECK(context->Global()
    4959             :             ->Set(context.local(), v8_str("12"), v8_num(92))
    4960             :             .FromJust());
    4961          30 :   CHECK(context->Global()
    4962             :             ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
    4963             :             .FromJust());
    4964          24 :   CHECK(context->Global()
    4965             :             ->Set(context.local(), v8_num(13), v8_num(56))
    4966             :             .FromJust());
    4967             :   Local<Value> foo = CompileRun("this.foo");
    4968          12 :   CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
    4969             :   Local<Value> twelve = CompileRun("this[12]");
    4970          12 :   CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
    4971             :   Local<Value> sixteen = CompileRun("this[16]");
    4972          12 :   CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
    4973             :   Local<Value> thirteen = CompileRun("this[13]");
    4974          12 :   CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
    4975          36 :   CHECK_EQ(92, context->Global()
    4976             :                    ->Get(context.local(), v8::Integer::New(isolate, 12))
    4977             :                    .ToLocalChecked()
    4978             :                    ->Int32Value(context.local())
    4979             :                    .FromJust());
    4980          36 :   CHECK_EQ(92, context->Global()
    4981             :                    ->Get(context.local(), v8_str("12"))
    4982             :                    .ToLocalChecked()
    4983             :                    ->Int32Value(context.local())
    4984             :                    .FromJust());
    4985          30 :   CHECK_EQ(92, context->Global()
    4986             :                    ->Get(context.local(), v8_num(12))
    4987             :                    .ToLocalChecked()
    4988             :                    ->Int32Value(context.local())
    4989             :                    .FromJust());
    4990          36 :   CHECK_EQ(32, context->Global()
    4991             :                    ->Get(context.local(), v8::Integer::New(isolate, 16))
    4992             :                    .ToLocalChecked()
    4993             :                    ->Int32Value(context.local())
    4994             :                    .FromJust());
    4995          36 :   CHECK_EQ(32, context->Global()
    4996             :                    ->Get(context.local(), v8_str("16"))
    4997             :                    .ToLocalChecked()
    4998             :                    ->Int32Value(context.local())
    4999             :                    .FromJust());
    5000          30 :   CHECK_EQ(32, context->Global()
    5001             :                    ->Get(context.local(), v8_num(16))
    5002             :                    .ToLocalChecked()
    5003             :                    ->Int32Value(context.local())
    5004             :                    .FromJust());
    5005          36 :   CHECK_EQ(56, context->Global()
    5006             :                    ->Get(context.local(), v8::Integer::New(isolate, 13))
    5007             :                    .ToLocalChecked()
    5008             :                    ->Int32Value(context.local())
    5009             :                    .FromJust());
    5010          36 :   CHECK_EQ(56, context->Global()
    5011             :                    ->Get(context.local(), v8_str("13"))
    5012             :                    .ToLocalChecked()
    5013             :                    ->Int32Value(context.local())
    5014             :                    .FromJust());
    5015          30 :   CHECK_EQ(56, context->Global()
    5016             :                    ->Get(context.local(), v8_num(13))
    5017             :                    .ToLocalChecked()
    5018             :                    ->Int32Value(context.local())
    5019           6 :                    .FromJust());
    5020           6 : }
    5021             : 
    5022             : 
    5023       23724 : THREADED_TEST(PropertyAttributes) {
    5024           6 :   LocalContext context;
    5025          12 :   v8::HandleScope scope(context->GetIsolate());
    5026             :   // none
    5027           6 :   Local<String> prop = v8_str("none");
    5028          30 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
    5029          24 :   CHECK_EQ(v8::None, context->Global()
    5030             :                          ->GetPropertyAttributes(context.local(), prop)
    5031             :                          .FromJust());
    5032             :   // read-only
    5033           6 :   prop = v8_str("read_only");
    5034             :   context->Global()
    5035          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
    5036          12 :       .FromJust();
    5037          36 :   CHECK_EQ(7, context->Global()
    5038             :                   ->Get(context.local(), prop)
    5039             :                   .ToLocalChecked()
    5040             :                   ->Int32Value(context.local())
    5041             :                   .FromJust());
    5042          24 :   CHECK_EQ(v8::ReadOnly, context->Global()
    5043             :                              ->GetPropertyAttributes(context.local(), prop)
    5044             :                              .FromJust());
    5045             :   CompileRun("read_only = 9");
    5046          36 :   CHECK_EQ(7, context->Global()
    5047             :                   ->Get(context.local(), prop)
    5048             :                   .ToLocalChecked()
    5049             :                   ->Int32Value(context.local())
    5050             :                   .FromJust());
    5051          30 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
    5052          36 :   CHECK_EQ(7, context->Global()
    5053             :                   ->Get(context.local(), prop)
    5054             :                   .ToLocalChecked()
    5055             :                   ->Int32Value(context.local())
    5056             :                   .FromJust());
    5057             :   // dont-delete
    5058           6 :   prop = v8_str("dont_delete");
    5059             :   context->Global()
    5060          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
    5061          12 :       .FromJust();
    5062          36 :   CHECK_EQ(13, context->Global()
    5063             :                    ->Get(context.local(), prop)
    5064             :                    .ToLocalChecked()
    5065             :                    ->Int32Value(context.local())
    5066             :                    .FromJust());
    5067             :   CompileRun("delete dont_delete");
    5068          36 :   CHECK_EQ(13, context->Global()
    5069             :                    ->Get(context.local(), prop)
    5070             :                    .ToLocalChecked()
    5071             :                    ->Int32Value(context.local())
    5072             :                    .FromJust());
    5073          24 :   CHECK_EQ(v8::DontDelete, context->Global()
    5074             :                                ->GetPropertyAttributes(context.local(), prop)
    5075             :                                .FromJust());
    5076             :   // dont-enum
    5077           6 :   prop = v8_str("dont_enum");
    5078             :   context->Global()
    5079          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
    5080          12 :       .FromJust();
    5081          24 :   CHECK_EQ(v8::DontEnum, context->Global()
    5082             :                              ->GetPropertyAttributes(context.local(), prop)
    5083             :                              .FromJust());
    5084             :   // absent
    5085           6 :   prop = v8_str("absent");
    5086          24 :   CHECK_EQ(v8::None, context->Global()
    5087             :                          ->GetPropertyAttributes(context.local(), prop)
    5088             :                          .FromJust());
    5089           6 :   Local<Value> fake_prop = v8_num(1);
    5090          24 :   CHECK_EQ(v8::None, context->Global()
    5091             :                          ->GetPropertyAttributes(context.local(), fake_prop)
    5092             :                          .FromJust());
    5093             :   // exception
    5094          12 :   TryCatch try_catch(context->GetIsolate());
    5095             :   Local<Value> exception =
    5096           6 :       CompileRun("({ toString: function() { throw 'exception';} })");
    5097          24 :   CHECK(context->Global()
    5098             :             ->GetPropertyAttributes(context.local(), exception)
    5099             :             .IsNothing());
    5100           6 :   CHECK(try_catch.HasCaught());
    5101             :   String::Utf8Value exception_value(context->GetIsolate(),
    5102          18 :                                     try_catch.Exception());
    5103           6 :   CHECK_EQ(0, strcmp("exception", *exception_value));
    5104          12 :   try_catch.Reset();
    5105           6 : }
    5106             : 
    5107             : 
    5108       23724 : THREADED_TEST(Array) {
    5109           6 :   LocalContext context;
    5110          12 :   v8::HandleScope scope(context->GetIsolate());
    5111           6 :   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
    5112           6 :   CHECK_EQ(0u, array->Length());
    5113          12 :   CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
    5114          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5115          12 :   CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
    5116          12 :   CHECK(!array->Has(context.local(), 100).FromJust());
    5117          12 :   CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
    5118           6 :   CHECK_EQ(3u, array->Length());
    5119          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5120          12 :   CHECK(!array->Has(context.local(), 1).FromJust());
    5121          12 :   CHECK(array->Has(context.local(), 2).FromJust());
    5122          18 :   CHECK_EQ(7, array->Get(context.local(), 2)
    5123             :                   .ToLocalChecked()
    5124             :                   ->Int32Value(context.local())
    5125             :                   .FromJust());
    5126             :   Local<Value> obj = CompileRun("[1, 2, 3]");
    5127             :   Local<v8::Array> arr = obj.As<v8::Array>();
    5128           6 :   CHECK_EQ(3u, arr->Length());
    5129          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5130             :                   .ToLocalChecked()
    5131             :                   ->Int32Value(context.local())
    5132             :                   .FromJust());
    5133          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5134             :                   .ToLocalChecked()
    5135             :                   ->Int32Value(context.local())
    5136             :                   .FromJust());
    5137          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5138             :                   .ToLocalChecked()
    5139             :                   ->Int32Value(context.local())
    5140             :                   .FromJust());
    5141           6 :   array = v8::Array::New(context->GetIsolate(), 27);
    5142           6 :   CHECK_EQ(27u, array->Length());
    5143           6 :   array = v8::Array::New(context->GetIsolate(), -27);
    5144          12 :   CHECK_EQ(0u, array->Length());
    5145           6 : }
    5146             : 
    5147             : 
    5148         180 : void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5149          30 :   v8::EscapableHandleScope scope(args.GetIsolate());
    5150          30 :   ApiTestFuzzer::Fuzz();
    5151          30 :   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
    5152         180 :   for (int i = 0; i < args.Length(); i++) {
    5153         180 :     CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
    5154             :               .FromJust());
    5155             :   }
    5156             :   args.GetReturnValue().Set(scope.Escape(result));
    5157          30 : }
    5158             : 
    5159             : 
    5160       23724 : THREADED_TEST(Vector) {
    5161           6 :   v8::Isolate* isolate = CcTest::isolate();
    5162           6 :   v8::HandleScope scope(isolate);
    5163           6 :   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
    5164          18 :   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
    5165          12 :   LocalContext context(0, global);
    5166             : 
    5167             :   const char* fun = "f()";
    5168             :   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
    5169           6 :   CHECK_EQ(0u, a0->Length());
    5170             : 
    5171             :   const char* fun2 = "f(11)";
    5172             :   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
    5173           6 :   CHECK_EQ(1u, a1->Length());
    5174          18 :   CHECK_EQ(11, a1->Get(context.local(), 0)
    5175             :                    .ToLocalChecked()
    5176             :                    ->Int32Value(context.local())
    5177             :                    .FromJust());
    5178             : 
    5179             :   const char* fun3 = "f(12, 13)";
    5180             :   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
    5181           6 :   CHECK_EQ(2u, a2->Length());
    5182          18 :   CHECK_EQ(12, a2->Get(context.local(), 0)
    5183             :                    .ToLocalChecked()
    5184             :                    ->Int32Value(context.local())
    5185             :                    .FromJust());
    5186          18 :   CHECK_EQ(13, a2->Get(context.local(), 1)
    5187             :                    .ToLocalChecked()
    5188             :                    ->Int32Value(context.local())
    5189             :                    .FromJust());
    5190             : 
    5191             :   const char* fun4 = "f(14, 15, 16)";
    5192             :   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
    5193           6 :   CHECK_EQ(3u, a3->Length());
    5194          18 :   CHECK_EQ(14, a3->Get(context.local(), 0)
    5195             :                    .ToLocalChecked()
    5196             :                    ->Int32Value(context.local())
    5197             :                    .FromJust());
    5198          18 :   CHECK_EQ(15, a3->Get(context.local(), 1)
    5199             :                    .ToLocalChecked()
    5200             :                    ->Int32Value(context.local())
    5201             :                    .FromJust());
    5202          18 :   CHECK_EQ(16, a3->Get(context.local(), 2)
    5203             :                    .ToLocalChecked()
    5204             :                    ->Int32Value(context.local())
    5205             :                    .FromJust());
    5206             : 
    5207             :   const char* fun5 = "f(17, 18, 19, 20)";
    5208             :   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
    5209           6 :   CHECK_EQ(4u, a4->Length());
    5210          18 :   CHECK_EQ(17, a4->Get(context.local(), 0)
    5211             :                    .ToLocalChecked()
    5212             :                    ->Int32Value(context.local())
    5213             :                    .FromJust());
    5214          18 :   CHECK_EQ(18, a4->Get(context.local(), 1)
    5215             :                    .ToLocalChecked()
    5216             :                    ->Int32Value(context.local())
    5217             :                    .FromJust());
    5218          18 :   CHECK_EQ(19, a4->Get(context.local(), 2)
    5219             :                    .ToLocalChecked()
    5220             :                    ->Int32Value(context.local())
    5221             :                    .FromJust());
    5222          18 :   CHECK_EQ(20, a4->Get(context.local(), 3)
    5223             :                    .ToLocalChecked()
    5224             :                    ->Int32Value(context.local())
    5225           6 :                    .FromJust());
    5226           6 : }
    5227             : 
    5228             : 
    5229       23724 : THREADED_TEST(FunctionCall) {
    5230           6 :   LocalContext context;
    5231           6 :   v8::Isolate* isolate = context->GetIsolate();
    5232          12 :   v8::HandleScope scope(isolate);
    5233             :   CompileRun(
    5234             :       "function Foo() {"
    5235             :       "  var result = [];"
    5236             :       "  for (var i = 0; i < arguments.length; i++) {"
    5237             :       "    result.push(arguments[i]);"
    5238             :       "  }"
    5239             :       "  return result;"
    5240             :       "}"
    5241             :       "function ReturnThisSloppy() {"
    5242             :       "  return this;"
    5243             :       "}"
    5244             :       "function ReturnThisStrict() {"
    5245             :       "  'use strict';"
    5246             :       "  return this;"
    5247             :       "}");
    5248             :   Local<Function> Foo = Local<Function>::Cast(
    5249          30 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5250             :   Local<Function> ReturnThisSloppy = Local<Function>::Cast(
    5251             :       context->Global()
    5252          24 :           ->Get(context.local(), v8_str("ReturnThisSloppy"))
    5253           6 :           .ToLocalChecked());
    5254             :   Local<Function> ReturnThisStrict = Local<Function>::Cast(
    5255             :       context->Global()
    5256          24 :           ->Get(context.local(), v8_str("ReturnThisStrict"))
    5257           6 :           .ToLocalChecked());
    5258             : 
    5259             :   v8::Local<Value>* args0 = nullptr;
    5260             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5261          12 :       Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
    5262           6 :   CHECK_EQ(0u, a0->Length());
    5263             : 
    5264           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5265             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5266          12 :       Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
    5267           6 :   CHECK_EQ(1u, a1->Length());
    5268          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5269             :                     .ToLocalChecked()
    5270             :                     ->NumberValue(context.local())
    5271             :                     .FromJust());
    5272             : 
    5273           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5274             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5275          12 :       Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
    5276           6 :   CHECK_EQ(2u, a2->Length());
    5277          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5278             :                     .ToLocalChecked()
    5279             :                     ->NumberValue(context.local())
    5280             :                     .FromJust());
    5281          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5282             :                     .ToLocalChecked()
    5283             :                     ->NumberValue(context.local())
    5284             :                     .FromJust());
    5285             : 
    5286           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5287             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5288          12 :       Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
    5289           6 :   CHECK_EQ(3u, a3->Length());
    5290          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5291             :                     .ToLocalChecked()
    5292             :                     ->NumberValue(context.local())
    5293             :                     .FromJust());
    5294          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5295             :                     .ToLocalChecked()
    5296             :                     ->NumberValue(context.local())
    5297             :                     .FromJust());
    5298          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5299             :                     .ToLocalChecked()
    5300             :                     ->NumberValue(context.local())
    5301             :                     .FromJust());
    5302             : 
    5303             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5304           6 :                               v8_num(10.11)};
    5305             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5306          12 :       Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
    5307           6 :   CHECK_EQ(4u, a4->Length());
    5308          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5309             :                     .ToLocalChecked()
    5310             :                     ->NumberValue(context.local())
    5311             :                     .FromJust());
    5312          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5313             :                     .ToLocalChecked()
    5314             :                     ->NumberValue(context.local())
    5315             :                     .FromJust());
    5316          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5317             :                     .ToLocalChecked()
    5318             :                     ->NumberValue(context.local())
    5319             :                     .FromJust());
    5320          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5321             :                       .ToLocalChecked()
    5322             :                       ->NumberValue(context.local())
    5323             :                       .FromJust());
    5324             : 
    5325             :   Local<v8::Value> r1 =
    5326             :       ReturnThisSloppy
    5327          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5328           6 :           .ToLocalChecked();
    5329          12 :   CHECK(r1->StrictEquals(context->Global()));
    5330             :   Local<v8::Value> r2 =
    5331          12 :       ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5332           6 :           .ToLocalChecked();
    5333          12 :   CHECK(r2->StrictEquals(context->Global()));
    5334             :   Local<v8::Value> r3 =
    5335           6 :       ReturnThisSloppy->Call(context.local(), v8_num(42), 0, nullptr)
    5336           6 :           .ToLocalChecked();
    5337           6 :   CHECK(r3->IsNumberObject());
    5338           6 :   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
    5339             :   Local<v8::Value> r4 =
    5340          18 :       ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, nullptr)
    5341           6 :           .ToLocalChecked();
    5342           6 :   CHECK(r4->IsStringObject());
    5343          18 :   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
    5344             :   Local<v8::Value> r5 =
    5345          12 :       ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, nullptr)
    5346           6 :           .ToLocalChecked();
    5347           6 :   CHECK(r5->IsBooleanObject());
    5348           6 :   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
    5349             : 
    5350             :   Local<v8::Value> r6 =
    5351             :       ReturnThisStrict
    5352          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5353           6 :           .ToLocalChecked();
    5354           6 :   CHECK(r6->IsUndefined());
    5355             :   Local<v8::Value> r7 =
    5356          12 :       ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5357           6 :           .ToLocalChecked();
    5358           6 :   CHECK(r7->IsNull());
    5359             :   Local<v8::Value> r8 =
    5360           6 :       ReturnThisStrict->Call(context.local(), v8_num(42), 0, nullptr)
    5361           6 :           .ToLocalChecked();
    5362           6 :   CHECK(r8->StrictEquals(v8_num(42)));
    5363             :   Local<v8::Value> r9 =
    5364          18 :       ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, nullptr)
    5365           6 :           .ToLocalChecked();
    5366          12 :   CHECK(r9->StrictEquals(v8_str("hello")));
    5367             :   Local<v8::Value> r10 =
    5368          12 :       ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, nullptr)
    5369           6 :           .ToLocalChecked();
    5370          12 :   CHECK(r10->StrictEquals(v8::True(isolate)));
    5371           6 : }
    5372             : 
    5373             : 
    5374       23724 : THREADED_TEST(ConstructCall) {
    5375           6 :   LocalContext context;
    5376           6 :   v8::Isolate* isolate = context->GetIsolate();
    5377          12 :   v8::HandleScope scope(isolate);
    5378             :   CompileRun(
    5379             :       "function Foo() {"
    5380             :       "  var result = [];"
    5381             :       "  for (var i = 0; i < arguments.length; i++) {"
    5382             :       "    result.push(arguments[i]);"
    5383             :       "  }"
    5384             :       "  return result;"
    5385             :       "}");
    5386             :   Local<Function> Foo = Local<Function>::Cast(
    5387          30 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5388             : 
    5389             :   v8::Local<Value>* args0 = nullptr;
    5390             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5391           6 :       Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
    5392           6 :   CHECK_EQ(0u, a0->Length());
    5393             : 
    5394           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5395             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5396           6 :       Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
    5397           6 :   CHECK_EQ(1u, a1->Length());
    5398          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5399             :                     .ToLocalChecked()
    5400             :                     ->NumberValue(context.local())
    5401             :                     .FromJust());
    5402             : 
    5403           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5404             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5405           6 :       Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
    5406           6 :   CHECK_EQ(2u, a2->Length());
    5407          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5408             :                     .ToLocalChecked()
    5409             :                     ->NumberValue(context.local())
    5410             :                     .FromJust());
    5411          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5412             :                     .ToLocalChecked()
    5413             :                     ->NumberValue(context.local())
    5414             :                     .FromJust());
    5415             : 
    5416           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5417             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5418           6 :       Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
    5419           6 :   CHECK_EQ(3u, a3->Length());
    5420          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5421             :                     .ToLocalChecked()
    5422             :                     ->NumberValue(context.local())
    5423             :                     .FromJust());
    5424          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5425             :                     .ToLocalChecked()
    5426             :                     ->NumberValue(context.local())
    5427             :                     .FromJust());
    5428          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5429             :                     .ToLocalChecked()
    5430             :                     ->NumberValue(context.local())
    5431             :                     .FromJust());
    5432             : 
    5433             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5434           6 :                               v8_num(10.11)};
    5435             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5436           6 :       Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
    5437           6 :   CHECK_EQ(4u, a4->Length());
    5438          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5439             :                     .ToLocalChecked()
    5440             :                     ->NumberValue(context.local())
    5441             :                     .FromJust());
    5442          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5443             :                     .ToLocalChecked()
    5444             :                     ->NumberValue(context.local())
    5445             :                     .FromJust());
    5446          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5447             :                     .ToLocalChecked()
    5448             :                     ->NumberValue(context.local())
    5449             :                     .FromJust());
    5450          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5451             :                       .ToLocalChecked()
    5452             :                       ->NumberValue(context.local())
    5453           6 :                       .FromJust());
    5454           6 : }
    5455             : 
    5456             : 
    5457       23724 : THREADED_TEST(ConversionNumber) {
    5458           6 :   LocalContext env;
    5459           6 :   v8::Isolate* isolate = env->GetIsolate();
    5460          12 :   v8::HandleScope scope(isolate);
    5461             :   // Very large number.
    5462             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5463             :   Local<Value> obj =
    5464          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5465          12 :   CHECK_EQ(5312874545152.0,
    5466             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5467          12 :   CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5468          12 :   CHECK_EQ(0, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5469             :   // Large number.
    5470             :   CompileRun("var obj = -1234567890123;");
    5471          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5472          12 :   CHECK_EQ(-1234567890123.0,
    5473             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5474          12 :   CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5475          18 :   CHECK_EQ(2382691125, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5476             :   // Small positive integer.
    5477             :   CompileRun("var obj = 42;");
    5478          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5479          12 :   CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5480          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5481          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5482             :   // Negative integer.
    5483             :   CompileRun("var obj = -37;");
    5484          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5485          12 :   CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5486          12 :   CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5487          18 :   CHECK_EQ(4294967259, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5488             :   // Positive non-int32 integer.
    5489             :   CompileRun("var obj = 0x81234567;");
    5490          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5491          12 :   CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5492          12 :   CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5493          18 :   CHECK_EQ(2166572391, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5494             :   // Fraction.
    5495             :   CompileRun("var obj = 42.3;");
    5496          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5497          12 :   CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5498          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5499          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5500             :   // Large negative fraction.
    5501             :   CompileRun("var obj = -5726623061.75;");
    5502          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5503          12 :   CHECK_EQ(-5726623061.75,
    5504             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5505          12 :   CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5506          24 :   CHECK_EQ(2863311531, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5507           6 : }
    5508             : 
    5509             : 
    5510       23724 : THREADED_TEST(isNumberType) {
    5511           6 :   LocalContext env;
    5512          12 :   v8::HandleScope scope(env->GetIsolate());
    5513             :   // Very large number.
    5514             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5515             :   Local<Value> obj =
    5516          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5517           6 :   CHECK(!obj->IsInt32());
    5518           6 :   CHECK(!obj->IsUint32());
    5519             :   // Large negative number.
    5520             :   CompileRun("var obj = -1234567890123;");
    5521          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5522           6 :   CHECK(!obj->IsInt32());
    5523           6 :   CHECK(!obj->IsUint32());
    5524             :   // Small positive integer.
    5525             :   CompileRun("var obj = 42;");
    5526          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5527           6 :   CHECK(obj->IsInt32());
    5528           6 :   CHECK(obj->IsUint32());
    5529             :   // Negative integer.
    5530             :   CompileRun("var obj = -37;");
    5531          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5532           6 :   CHECK(obj->IsInt32());
    5533           6 :   CHECK(!obj->IsUint32());
    5534             :   // Positive non-int32 integer.
    5535             :   CompileRun("var obj = 0x81234567;");
    5536          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5537           6 :   CHECK(!obj->IsInt32());
    5538           6 :   CHECK(obj->IsUint32());
    5539             :   // Fraction.
    5540             :   CompileRun("var obj = 42.3;");
    5541          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5542           6 :   CHECK(!obj->IsInt32());
    5543           6 :   CHECK(!obj->IsUint32());
    5544             :   // Large negative fraction.
    5545             :   CompileRun("var obj = -5726623061.75;");
    5546          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5547           6 :   CHECK(!obj->IsInt32());
    5548           6 :   CHECK(!obj->IsUint32());
    5549             :   // Positive zero
    5550             :   CompileRun("var obj = 0.0;");
    5551          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5552           6 :   CHECK(obj->IsInt32());
    5553           6 :   CHECK(obj->IsUint32());
    5554             :   // Positive zero
    5555             :   CompileRun("var obj = -0.0;");
    5556          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5557           6 :   CHECK(!obj->IsInt32());
    5558          12 :   CHECK(!obj->IsUint32());
    5559           6 : }
    5560             : 
    5561          54 : static void CheckUncle(v8::Isolate* isolate, v8::TryCatch* try_catch) {
    5562          54 :   CHECK(try_catch->HasCaught());
    5563          54 :   String::Utf8Value str_value(isolate, try_catch->Exception());
    5564          54 :   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
    5565          54 :   try_catch->Reset();
    5566          54 : }
    5567             : 
    5568       23724 : THREADED_TEST(ConversionException) {
    5569           6 :   LocalContext env;
    5570           6 :   v8::Isolate* isolate = env->GetIsolate();
    5571          12 :   v8::HandleScope scope(isolate);
    5572             :   CompileRun(
    5573             :       "function TestClass() { };"
    5574             :       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
    5575             :       "var obj = new TestClass();");
    5576             :   Local<Value> obj =
    5577          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5578             : 
    5579          12 :   v8::TryCatch try_catch(isolate);
    5580             : 
    5581          12 :   CHECK(obj->ToString(env.local()).IsEmpty());
    5582           6 :   CheckUncle(isolate, &try_catch);
    5583             : 
    5584          12 :   CHECK(obj->ToNumber(env.local()).IsEmpty());
    5585           6 :   CheckUncle(isolate, &try_catch);
    5586             : 
    5587          12 :   CHECK(obj->ToInteger(env.local()).IsEmpty());
    5588           6 :   CheckUncle(isolate, &try_catch);
    5589             : 
    5590          12 :   CHECK(obj->ToUint32(env.local()).IsEmpty());
    5591           6 :   CheckUncle(isolate, &try_catch);
    5592             : 
    5593          12 :   CHECK(obj->ToInt32(env.local()).IsEmpty());
    5594           6 :   CheckUncle(isolate, &try_catch);
    5595             : 
    5596          18 :   CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
    5597           6 :   CHECK(try_catch.HasCaught());
    5598           6 :   try_catch.Reset();
    5599             : 
    5600          12 :   CHECK(obj->Int32Value(env.local()).IsNothing());
    5601           6 :   CheckUncle(isolate, &try_catch);
    5602             : 
    5603          12 :   CHECK(obj->Uint32Value(env.local()).IsNothing());
    5604           6 :   CheckUncle(isolate, &try_catch);
    5605             : 
    5606          12 :   CHECK(obj->NumberValue(env.local()).IsNothing());
    5607           6 :   CheckUncle(isolate, &try_catch);
    5608             : 
    5609          12 :   CHECK(obj->IntegerValue(env.local()).IsNothing());
    5610          12 :   CheckUncle(isolate, &try_catch);
    5611           6 : }
    5612             : 
    5613             : 
    5614          56 : void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5615          28 :   ApiTestFuzzer::Fuzz();
    5616          56 :   args.GetIsolate()->ThrowException(v8_str("konto"));
    5617          28 : }
    5618             : 
    5619             : 
    5620          25 : void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5621           5 :   if (args.Length() < 1) {
    5622             :     args.GetReturnValue().Set(false);
    5623           5 :     return;
    5624             :   }
    5625           5 :   v8::HandleScope scope(args.GetIsolate());
    5626          10 :   v8::TryCatch try_catch(args.GetIsolate());
    5627             :   Local<Value> result =
    5628             :       CompileRun(args[0]
    5629           5 :                      ->ToString(args.GetIsolate()->GetCurrentContext())
    5630          10 :                      .ToLocalChecked());
    5631          10 :   CHECK(!try_catch.HasCaught() || result.IsEmpty());
    5632          10 :   args.GetReturnValue().Set(try_catch.HasCaught());
    5633             : }
    5634             : 
    5635             : 
    5636       23724 : THREADED_TEST(APICatch) {
    5637           6 :   v8::Isolate* isolate = CcTest::isolate();
    5638           6 :   v8::HandleScope scope(isolate);
    5639           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5640             :   templ->Set(v8_str("ThrowFromC"),
    5641          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5642          12 :   LocalContext context(0, templ);
    5643             :   CompileRun(
    5644             :       "var thrown = false;"
    5645             :       "try {"
    5646             :       "  ThrowFromC();"
    5647             :       "} catch (e) {"
    5648             :       "  thrown = true;"
    5649             :       "}");
    5650             :   Local<Value> thrown = context->Global()
    5651          24 :                             ->Get(context.local(), v8_str("thrown"))
    5652           6 :                             .ToLocalChecked();
    5653          18 :   CHECK(thrown->BooleanValue(context.local()).FromJust());
    5654           6 : }
    5655             : 
    5656             : 
    5657       23724 : THREADED_TEST(APIThrowTryCatch) {
    5658           6 :   v8::Isolate* isolate = CcTest::isolate();
    5659           6 :   v8::HandleScope scope(isolate);
    5660           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5661             :   templ->Set(v8_str("ThrowFromC"),
    5662          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5663          12 :   LocalContext context(0, templ);
    5664          12 :   v8::TryCatch try_catch(isolate);
    5665             :   CompileRun("ThrowFromC();");
    5666          12 :   CHECK(try_catch.HasCaught());
    5667           6 : }
    5668             : 
    5669             : 
    5670             : // Test that a try-finally block doesn't shadow a try-catch block
    5671             : // when setting up an external handler.
    5672             : //
    5673             : // BUG(271): Some of the exception propagation does not work on the
    5674             : // ARM simulator because the simulator separates the C++ stack and the
    5675             : // JS stack.  This test therefore fails on the simulator.  The test is
    5676             : // not threaded to allow the threading tests to run on the simulator.
    5677       23723 : TEST(TryCatchInTryFinally) {
    5678           5 :   v8::Isolate* isolate = CcTest::isolate();
    5679           5 :   v8::HandleScope scope(isolate);
    5680           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5681          15 :   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
    5682          10 :   LocalContext context(0, templ);
    5683             :   Local<Value> result = CompileRun(
    5684             :       "try {"
    5685             :       "  try {"
    5686             :       "    CCatcher('throw 7;');"
    5687             :       "  } finally {"
    5688             :       "  }"
    5689             :       "} catch (e) {"
    5690             :       "}");
    5691          10 :   CHECK(result->IsTrue());
    5692           5 : }
    5693             : 
    5694             : 
    5695           5 : static void check_custom_error_tostring(v8::Local<v8::Message> message,
    5696             :                                         v8::Local<v8::Value> data) {
    5697             :   const char* uncaught_error = "Uncaught MyError toString";
    5698          25 :   CHECK(message->Get()
    5699             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5700             :                      v8_str(uncaught_error))
    5701             :             .FromJust());
    5702           5 : }
    5703             : 
    5704             : 
    5705       23723 : TEST(CustomErrorToString) {
    5706           5 :   LocalContext context;
    5707          10 :   v8::HandleScope scope(context->GetIsolate());
    5708           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
    5709             :   CompileRun(
    5710             :       "function MyError(name, message) {                   "
    5711             :       "  this.name = name;                                 "
    5712             :       "  this.message = message;                           "
    5713             :       "}                                                   "
    5714             :       "MyError.prototype = Object.create(Error.prototype); "
    5715             :       "MyError.prototype.toString = function() {           "
    5716             :       "  return 'MyError toString';                        "
    5717             :       "};                                                  "
    5718             :       "throw new MyError('my name', 'my message');         ");
    5719          10 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
    5720           5 : }
    5721             : 
    5722             : 
    5723          15 : static void check_custom_error_message(v8::Local<v8::Message> message,
    5724             :                                        v8::Local<v8::Value> data) {
    5725             :   const char* uncaught_error = "Uncaught MyError: my message";
    5726          45 :   printf("%s\n", *v8::String::Utf8Value(CcTest::isolate(), message->Get()));
    5727          60 :   CHECK(message->Get()
    5728             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5729             :                      v8_str(uncaught_error))
    5730             :             .FromJust());
    5731          15 : }
    5732             : 
    5733             : 
    5734       23723 : TEST(CustomErrorMessage) {
    5735           5 :   LocalContext context;
    5736          10 :   v8::HandleScope scope(context->GetIsolate());
    5737           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_message);
    5738             : 
    5739             :   // Handlebars.
    5740             :   CompileRun(
    5741             :       "function MyError(msg) {                             "
    5742             :       "  this.name = 'MyError';                            "
    5743             :       "  this.message = msg;                               "
    5744             :       "}                                                   "
    5745             :       "MyError.prototype = new Error();                    "
    5746             :       "throw new MyError('my message');                    ");
    5747             : 
    5748             :   // Closure.
    5749             :   CompileRun(
    5750             :       "function MyError(msg) {                             "
    5751             :       "  this.name = 'MyError';                            "
    5752             :       "  this.message = msg;                               "
    5753             :       "}                                                   "
    5754             :       "inherits = function(childCtor, parentCtor) {        "
    5755             :       "    function tempCtor() {};                         "
    5756             :       "    tempCtor.prototype = parentCtor.prototype;      "
    5757             :       "    childCtor.superClass_ = parentCtor.prototype;   "
    5758             :       "    childCtor.prototype = new tempCtor();           "
    5759             :       "    childCtor.prototype.constructor = childCtor;    "
    5760             :       "};                                                  "
    5761             :       "inherits(MyError, Error);                           "
    5762             :       "throw new MyError('my message');                    ");
    5763             : 
    5764             :   // Object.create.
    5765             :   CompileRun(
    5766             :       "function MyError(msg) {                             "
    5767             :       "  this.name = 'MyError';                            "
    5768             :       "  this.message = msg;                               "
    5769             :       "}                                                   "
    5770             :       "MyError.prototype = Object.create(Error.prototype); "
    5771             :       "throw new MyError('my message');                    ");
    5772             : 
    5773          10 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
    5774           5 : }
    5775             : 
    5776             : 
    5777           5 : static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
    5778             :                                             v8::Local<v8::Value> data) {
    5779             :   const char* uncaught_error = "Uncaught exception";
    5780          25 :   CHECK(message->Get()
    5781             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5782             :                      v8_str(uncaught_error))
    5783             :             .FromJust());
    5784           5 : }
    5785             : 
    5786             : 
    5787       23723 : TEST(CustomErrorRethrowsOnToString) {
    5788           5 :   LocalContext context;
    5789          10 :   v8::HandleScope scope(context->GetIsolate());
    5790           5 :   context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
    5791             : 
    5792             :   CompileRun(
    5793             :       "var e = { toString: function() { throw e; } };"
    5794             :       "try { throw e; } finally {}");
    5795             : 
    5796             :   context->GetIsolate()->RemoveMessageListeners(
    5797          10 :       check_custom_rethrowing_message);
    5798           5 : }
    5799             : 
    5800             : 
    5801          15 : static void receive_message(v8::Local<v8::Message> message,
    5802             :                             v8::Local<v8::Value> data) {
    5803          15 :   message->Get();
    5804          15 :   message_received = true;
    5805          15 : }
    5806             : 
    5807             : 
    5808       23723 : TEST(APIThrowMessage) {
    5809           5 :   message_received = false;
    5810           5 :   v8::Isolate* isolate = CcTest::isolate();
    5811           5 :   v8::HandleScope scope(isolate);
    5812           5 :   isolate->AddMessageListener(receive_message);
    5813           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5814             :   templ->Set(v8_str("ThrowFromC"),
    5815          15 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5816          10 :   LocalContext context(0, templ);
    5817             :   CompileRun("ThrowFromC();");
    5818           5 :   CHECK(message_received);
    5819          10 :   isolate->RemoveMessageListeners(receive_message);
    5820           5 : }
    5821             : 
    5822             : 
    5823       23723 : TEST(APIThrowMessageAndVerboseTryCatch) {
    5824           5 :   message_received = false;
    5825           5 :   v8::Isolate* isolate = CcTest::isolate();
    5826           5 :   v8::HandleScope scope(isolate);
    5827           5 :   isolate->AddMessageListener(receive_message);
    5828           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5829             :   templ->Set(v8_str("ThrowFromC"),
    5830          15 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5831          10 :   LocalContext context(0, templ);
    5832          10 :   v8::TryCatch try_catch(isolate);
    5833           5 :   try_catch.SetVerbose(true);
    5834             :   Local<Value> result = CompileRun("ThrowFromC();");
    5835           5 :   CHECK(try_catch.HasCaught());
    5836           5 :   CHECK(result.IsEmpty());
    5837           5 :   CHECK(message_received);
    5838          10 :   isolate->RemoveMessageListeners(receive_message);
    5839           5 : }
    5840             : 
    5841             : 
    5842       23723 : TEST(APIStackOverflowAndVerboseTryCatch) {
    5843           5 :   message_received = false;
    5844           5 :   LocalContext context;
    5845          10 :   v8::HandleScope scope(context->GetIsolate());
    5846           5 :   context->GetIsolate()->AddMessageListener(receive_message);
    5847          10 :   v8::TryCatch try_catch(context->GetIsolate());
    5848           5 :   try_catch.SetVerbose(true);
    5849             :   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
    5850           5 :   CHECK(try_catch.HasCaught());
    5851           5 :   CHECK(result.IsEmpty());
    5852           5 :   CHECK(message_received);
    5853          10 :   context->GetIsolate()->RemoveMessageListeners(receive_message);
    5854           5 : }
    5855             : 
    5856             : 
    5857       23724 : THREADED_TEST(ExternalScriptException) {
    5858           6 :   v8::Isolate* isolate = CcTest::isolate();
    5859           6 :   v8::HandleScope scope(isolate);
    5860           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5861             :   templ->Set(v8_str("ThrowFromC"),
    5862          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5863          12 :   LocalContext context(0, templ);
    5864             : 
    5865          12 :   v8::TryCatch try_catch(isolate);
    5866             :   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
    5867           6 :   CHECK(result.IsEmpty());
    5868           6 :   CHECK(try_catch.HasCaught());
    5869          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    5870          12 :   CHECK_EQ(0, strcmp("konto", *exception_value));
    5871           6 : }
    5872             : 
    5873             : 
    5874         370 : void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5875          85 :   ApiTestFuzzer::Fuzz();
    5876          85 :   CHECK_EQ(4, args.Length());
    5877          85 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    5878         170 :   int count = args[0]->Int32Value(context).FromJust();
    5879         170 :   int cInterval = args[2]->Int32Value(context).FromJust();
    5880          85 :   if (count == 0) {
    5881          10 :     args.GetIsolate()->ThrowException(v8_str("FromC"));
    5882           5 :     return;
    5883             :   } else {
    5884          80 :     Local<v8::Object> global = context->Global();
    5885             :     Local<Value> fun =
    5886         240 :         global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
    5887         320 :     v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
    5888          80 :     if (count % cInterval == 0) {
    5889          30 :       v8::TryCatch try_catch(args.GetIsolate());
    5890             :       Local<Value> result = fun.As<Function>()
    5891          30 :                                 ->Call(context, global, 4, argv)
    5892          60 :                                 .FromMaybe(Local<Value>());
    5893          60 :       int expected = args[3]->Int32Value(context).FromJust();
    5894          30 :       if (try_catch.HasCaught()) {
    5895          15 :         CHECK_EQ(expected, count);
    5896          15 :         CHECK(result.IsEmpty());
    5897          15 :         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
    5898             :       } else {
    5899          15 :         CHECK_NE(expected, count);
    5900             :       }
    5901             :       args.GetReturnValue().Set(result);
    5902          30 :       return;
    5903             :     } else {
    5904             :       args.GetReturnValue().Set(fun.As<Function>()
    5905          50 :                                     ->Call(context, global, 4, argv)
    5906         100 :                                     .FromMaybe(v8::Local<v8::Value>()));
    5907          50 :       return;
    5908             :     }
    5909             :   }
    5910             : }
    5911             : 
    5912             : 
    5913          75 : void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5914          25 :   ApiTestFuzzer::Fuzz();
    5915          25 :   CHECK_EQ(3, args.Length());
    5916          25 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    5917          50 :   bool equality = args[0]->BooleanValue(context).FromJust();
    5918          50 :   int count = args[1]->Int32Value(context).FromJust();
    5919          50 :   int expected = args[2]->Int32Value(context).FromJust();
    5920          25 :   if (equality) {
    5921          15 :     CHECK_EQ(count, expected);
    5922             :   } else {
    5923          10 :     CHECK_NE(count, expected);
    5924             :   }
    5925          25 : }
    5926             : 
    5927             : 
    5928       23724 : THREADED_TEST(EvalInTryFinally) {
    5929           6 :   LocalContext context;
    5930          12 :   v8::HandleScope scope(context->GetIsolate());
    5931          12 :   v8::TryCatch try_catch(context->GetIsolate());
    5932             :   CompileRun(
    5933             :       "(function() {"
    5934             :       "  try {"
    5935             :       "    eval('asldkf (*&^&*^');"
    5936             :       "  } finally {"
    5937             :       "    return;"
    5938             :       "  }"
    5939             :       "})()");
    5940          12 :   CHECK(!try_catch.HasCaught());
    5941           6 : }
    5942             : 
    5943             : 
    5944             : // This test works by making a stack of alternating JavaScript and C
    5945             : // activations.  These activations set up exception handlers with regular
    5946             : // intervals, one interval for C activations and another for JavaScript
    5947             : // activations.  When enough activations have been created an exception is
    5948             : // thrown and we check that the right activation catches the exception and that
    5949             : // no other activations do.  The right activation is always the topmost one with
    5950             : // a handler, regardless of whether it is in JavaScript or C.
    5951             : //
    5952             : // The notation used to describe a test case looks like this:
    5953             : //
    5954             : //    *JS[4] *C[3] @JS[2] C[1] JS[0]
    5955             : //
    5956             : // Each entry is an activation, either JS or C.  The index is the count at that
    5957             : // level.  Stars identify activations with exception handlers, the @ identifies
    5958             : // the exception handler that should catch the exception.
    5959             : //
    5960             : // BUG(271): Some of the exception propagation does not work on the
    5961             : // ARM simulator because the simulator separates the C++ stack and the
    5962             : // JS stack.  This test therefore fails on the simulator.  The test is
    5963             : // not threaded to allow the threading tests to run on the simulator.
    5964       23723 : TEST(ExceptionOrder) {
    5965           5 :   v8::Isolate* isolate = CcTest::isolate();
    5966           5 :   v8::HandleScope scope(isolate);
    5967           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5968          15 :   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
    5969             :   templ->Set(v8_str("CThrowCountDown"),
    5970          15 :              v8::FunctionTemplate::New(isolate, CThrowCountDown));
    5971          10 :   LocalContext context(0, templ);
    5972             :   CompileRun(
    5973             :       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
    5974             :       "  if (count == 0) throw 'FromJS';"
    5975             :       "  if (count % jsInterval == 0) {"
    5976             :       "    try {"
    5977             :       "      var value = CThrowCountDown(count - 1,"
    5978             :       "                                  jsInterval,"
    5979             :       "                                  cInterval,"
    5980             :       "                                  expected);"
    5981             :       "      check(false, count, expected);"
    5982             :       "      return value;"
    5983             :       "    } catch (e) {"
    5984             :       "      check(true, count, expected);"
    5985             :       "    }"
    5986             :       "  } else {"
    5987             :       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
    5988             :       "  }"
    5989             :       "}");
    5990             :   Local<Function> fun = Local<Function>::Cast(
    5991             :       context->Global()
    5992          20 :           ->Get(context.local(), v8_str("JSThrowCountDown"))
    5993           5 :           .ToLocalChecked());
    5994             : 
    5995             :   const int argc = 4;
    5996             :   //                             count      jsInterval cInterval  expected
    5997             : 
    5998             :   // *JS[4] *C[3] @JS[2] C[1] JS[0]
    5999           5 :   v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
    6000          10 :   fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
    6001             : 
    6002             :   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
    6003           5 :   v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
    6004          10 :   fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
    6005             : 
    6006             :   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6007           5 :   v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
    6008          10 :   fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
    6009             : 
    6010             :   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6011           5 :   v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
    6012          10 :   fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
    6013             : 
    6014             :   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
    6015           5 :   v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
    6016          10 :   fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
    6017             : 
    6018             :   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
    6019           5 :   v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
    6020          15 :   fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
    6021           5 : }
    6022             : 
    6023             : 
    6024         162 : void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6025          54 :   ApiTestFuzzer::Fuzz();
    6026          54 :   CHECK_EQ(1, args.Length());
    6027          54 :   args.GetIsolate()->ThrowException(args[0]);
    6028          54 : }
    6029             : 
    6030             : 
    6031       23724 : THREADED_TEST(ThrowValues) {
    6032           6 :   v8::Isolate* isolate = CcTest::isolate();
    6033           6 :   v8::HandleScope scope(isolate);
    6034           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6035          18 :   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
    6036          12 :   LocalContext context(0, templ);
    6037             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
    6038             :       CompileRun("function Run(obj) {"
    6039             :                  "  try {"
    6040             :                  "    Throw(obj);"
    6041             :                  "  } catch (e) {"
    6042             :                  "    return e;"
    6043             :                  "  }"
    6044             :                  "  return 'no exception';"
    6045             :                  "}"
    6046             :                  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
    6047           6 :   CHECK_EQ(5u, result->Length());
    6048          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
    6049             :             .ToLocalChecked()
    6050             :             ->IsString());
    6051          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
    6052             :             .ToLocalChecked()
    6053             :             ->IsNumber());
    6054          24 :   CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
    6055             :                   .ToLocalChecked()
    6056             :                   ->Int32Value(context.local())
    6057             :                   .FromJust());
    6058          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
    6059             :             .ToLocalChecked()
    6060             :             ->IsNumber());
    6061          24 :   CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
    6062             :                   .ToLocalChecked()
    6063             :                   ->Int32Value(context.local())
    6064             :                   .FromJust());
    6065          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
    6066             :             .ToLocalChecked()
    6067             :             ->IsNull());
    6068          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
    6069             :             .ToLocalChecked()
    6070           6 :             ->IsUndefined());
    6071           6 : }
    6072             : 
    6073             : 
    6074       23724 : THREADED_TEST(CatchZero) {
    6075           6 :   LocalContext context;
    6076          12 :   v8::HandleScope scope(context->GetIsolate());
    6077          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6078           6 :   CHECK(!try_catch.HasCaught());
    6079             :   CompileRun("throw 10");
    6080           6 :   CHECK(try_catch.HasCaught());
    6081          18 :   CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6082           6 :   try_catch.Reset();
    6083           6 :   CHECK(!try_catch.HasCaught());
    6084             :   CompileRun("throw 0");
    6085           6 :   CHECK(try_catch.HasCaught());
    6086          24 :   CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6087           6 : }
    6088             : 
    6089             : 
    6090       23724 : THREADED_TEST(CatchExceptionFromWith) {
    6091           6 :   LocalContext context;
    6092          12 :   v8::HandleScope scope(context->GetIsolate());
    6093          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6094           6 :   CHECK(!try_catch.HasCaught());
    6095             :   CompileRun("var o = {}; with (o) { throw 42; }");
    6096          12 :   CHECK(try_catch.HasCaught());
    6097           6 : }
    6098             : 
    6099             : 
    6100       23724 : THREADED_TEST(TryCatchAndFinallyHidingException) {
    6101           6 :   LocalContext context;
    6102          12 :   v8::HandleScope scope(context->GetIsolate());
    6103          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6104           6 :   CHECK(!try_catch.HasCaught());
    6105             :   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
    6106             :   CompileRun("f({toString: function() { throw 42; }});");
    6107          12 :   CHECK(!try_catch.HasCaught());
    6108           6 : }
    6109             : 
    6110             : 
    6111           6 : void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6112           6 :   v8::TryCatch try_catch(args.GetIsolate());
    6113           6 : }
    6114             : 
    6115             : 
    6116       23724 : THREADED_TEST(TryCatchAndFinally) {
    6117           6 :   LocalContext context;
    6118           6 :   v8::Isolate* isolate = context->GetIsolate();
    6119          12 :   v8::HandleScope scope(isolate);
    6120          48 :   CHECK(context->Global()
    6121             :             ->Set(context.local(), v8_str("native_with_try_catch"),
    6122             :                   v8::FunctionTemplate::New(isolate, WithTryCatch)
    6123             :                       ->GetFunction(context.local())
    6124             :                       .ToLocalChecked())
    6125             :             .FromJust());
    6126          12 :   v8::TryCatch try_catch(isolate);
    6127           6 :   CHECK(!try_catch.HasCaught());
    6128             :   CompileRun(
    6129             :       "try {\n"
    6130             :       "  throw new Error('a');\n"
    6131             :       "} finally {\n"
    6132             :       "  native_with_try_catch();\n"
    6133             :       "}\n");
    6134          12 :   CHECK(try_catch.HasCaught());
    6135           6 : }
    6136             : 
    6137             : 
    6138          30 : static void TryCatchNested1Helper(int depth) {
    6139          30 :   if (depth > 0) {
    6140          25 :     v8::TryCatch try_catch(CcTest::isolate());
    6141          25 :     try_catch.SetVerbose(true);
    6142          25 :     TryCatchNested1Helper(depth - 1);
    6143          25 :     CHECK(try_catch.HasCaught());
    6144          25 :     try_catch.ReThrow();
    6145             :   } else {
    6146          10 :     CcTest::isolate()->ThrowException(v8_str("E1"));
    6147             :   }
    6148          30 : }
    6149             : 
    6150             : 
    6151          30 : static void TryCatchNested2Helper(int depth) {
    6152          30 :   if (depth > 0) {
    6153          25 :     v8::TryCatch try_catch(CcTest::isolate());
    6154          25 :     try_catch.SetVerbose(true);
    6155          25 :     TryCatchNested2Helper(depth - 1);
    6156          25 :     CHECK(try_catch.HasCaught());
    6157          25 :     try_catch.ReThrow();
    6158             :   } else {
    6159             :     CompileRun("throw 'E2';");
    6160             :   }
    6161          30 : }
    6162             : 
    6163             : 
    6164       23723 : TEST(TryCatchNested) {
    6165           5 :   v8::V8::Initialize();
    6166           5 :   LocalContext context;
    6167          10 :   v8::HandleScope scope(context->GetIsolate());
    6168             : 
    6169             :   {
    6170             :     // Test nested try-catch with a native throw in the end.
    6171           5 :     v8::TryCatch try_catch(context->GetIsolate());
    6172           5 :     TryCatchNested1Helper(5);
    6173           5 :     CHECK(try_catch.HasCaught());
    6174          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6175             :                                               try_catch.Exception()),
    6176           5 :                        "E1"));
    6177             :   }
    6178             : 
    6179             :   {
    6180             :     // Test nested try-catch with a JavaScript throw in the end.
    6181           5 :     v8::TryCatch try_catch(context->GetIsolate());
    6182           5 :     TryCatchNested2Helper(5);
    6183           5 :     CHECK(try_catch.HasCaught());
    6184          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6185             :                                               try_catch.Exception()),
    6186           5 :                        "E2"));
    6187           5 :   }
    6188           5 : }
    6189             : 
    6190             : 
    6191          10 : void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
    6192          10 :   CHECK(try_catch->HasCaught());
    6193          10 :   Local<Message> message = try_catch->Message();
    6194          10 :   Local<Value> resource = message->GetScriptOrigin().ResourceName();
    6195          10 :   CHECK_EQ(
    6196             :       0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), resource), "inner"));
    6197          20 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), message->Get()),
    6198             :                      "Uncaught Error: a"));
    6199          20 :   CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
    6200             :                   .FromJust());
    6201          20 :   CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
    6202             :                   .FromJust());
    6203          10 : }
    6204             : 
    6205             : 
    6206           5 : void TryCatchMixedNestingHelper(
    6207           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6208           5 :   ApiTestFuzzer::Fuzz();
    6209           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6210           5 :   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
    6211           5 :   CHECK(try_catch.HasCaught());
    6212           5 :   TryCatchMixedNestingCheck(&try_catch);
    6213           5 :   try_catch.ReThrow();
    6214           5 : }
    6215             : 
    6216             : 
    6217             : // This test ensures that an outer TryCatch in the following situation:
    6218             : //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
    6219             : // does not clobber the Message object generated for the inner TryCatch.
    6220             : // This exercises the ability of TryCatch.ReThrow() to restore the
    6221             : // inner pending Message before throwing the exception again.
    6222       23723 : TEST(TryCatchMixedNesting) {
    6223           5 :   v8::Isolate* isolate = CcTest::isolate();
    6224           5 :   v8::HandleScope scope(isolate);
    6225           5 :   v8::V8::Initialize();
    6226          10 :   v8::TryCatch try_catch(isolate);
    6227           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6228             :   templ->Set(v8_str("TryCatchMixedNestingHelper"),
    6229          15 :              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
    6230          10 :   LocalContext context(0, templ);
    6231           5 :   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
    6232          10 :   TryCatchMixedNestingCheck(&try_catch);
    6233           5 : }
    6234             : 
    6235             : 
    6236          15 : void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6237           5 :   ApiTestFuzzer::Fuzz();
    6238           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6239          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6240           5 :   CHECK(try_catch.HasCaught());
    6241           5 : }
    6242             : 
    6243             : 
    6244       23723 : TEST(TryCatchNative) {
    6245           5 :   v8::Isolate* isolate = CcTest::isolate();
    6246           5 :   v8::HandleScope scope(isolate);
    6247           5 :   v8::V8::Initialize();
    6248          10 :   v8::TryCatch try_catch(isolate);
    6249           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6250             :   templ->Set(v8_str("TryCatchNativeHelper"),
    6251          15 :              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
    6252          10 :   LocalContext context(0, templ);
    6253             :   CompileRun("TryCatchNativeHelper();");
    6254          10 :   CHECK(!try_catch.HasCaught());
    6255           5 : }
    6256             : 
    6257             : 
    6258           5 : void TryCatchNativeResetHelper(
    6259          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6260           5 :   ApiTestFuzzer::Fuzz();
    6261           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6262          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6263           5 :   CHECK(try_catch.HasCaught());
    6264           5 :   try_catch.Reset();
    6265           5 :   CHECK(!try_catch.HasCaught());
    6266           5 : }
    6267             : 
    6268             : 
    6269       23723 : TEST(TryCatchNativeReset) {
    6270           5 :   v8::Isolate* isolate = CcTest::isolate();
    6271           5 :   v8::HandleScope scope(isolate);
    6272           5 :   v8::V8::Initialize();
    6273          10 :   v8::TryCatch try_catch(isolate);
    6274           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6275             :   templ->Set(v8_str("TryCatchNativeResetHelper"),
    6276          15 :              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
    6277          10 :   LocalContext context(0, templ);
    6278             :   CompileRun("TryCatchNativeResetHelper();");
    6279          10 :   CHECK(!try_catch.HasCaught());
    6280           5 : }
    6281             : 
    6282             : 
    6283       23724 : THREADED_TEST(Equality) {
    6284           6 :   LocalContext context;
    6285           6 :   v8::Isolate* isolate = context->GetIsolate();
    6286          12 :   v8::HandleScope scope(context->GetIsolate());
    6287             :   // Check that equality works at all before relying on CHECK_EQ
    6288          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6289          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6290             : 
    6291          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6292          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6293          18 :   CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
    6294          18 :   CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
    6295          18 :   CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
    6296             : 
    6297             :   // Assume String is not internalized.
    6298          18 :   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
    6299          18 :   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
    6300          12 :   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
    6301          12 :   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
    6302          12 :   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
    6303          12 :   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
    6304           6 :   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
    6305           6 :   CHECK(!not_a_number->StrictEquals(not_a_number));
    6306           6 :   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
    6307           6 :   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
    6308             : 
    6309           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    6310             :   v8::Persistent<v8::Object> alias(isolate, obj);
    6311           6 :   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
    6312             :   alias.Reset();
    6313             : 
    6314          18 :   CHECK(v8_str("a")->SameValue(v8_str("a")));
    6315          18 :   CHECK(!v8_str("a")->SameValue(v8_str("b")));
    6316          12 :   CHECK(!v8_str("5")->SameValue(v8_num(5)));
    6317          12 :   CHECK(v8_num(1)->SameValue(v8_num(1)));
    6318          12 :   CHECK(!v8_num(1)->SameValue(v8_num(2)));
    6319          12 :   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
    6320           6 :   CHECK(not_a_number->SameValue(not_a_number));
    6321           6 :   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
    6322          12 :   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
    6323           6 : }
    6324             : 
    6325       23724 : THREADED_TEST(TypeOf) {
    6326           6 :   LocalContext context;
    6327           6 :   v8::Isolate* isolate = context->GetIsolate();
    6328          12 :   v8::HandleScope scope(context->GetIsolate());
    6329             : 
    6330           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
    6331          12 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
    6332             : 
    6333          30 :   CHECK(v8::Undefined(isolate)
    6334             :             ->TypeOf(isolate)
    6335             :             ->Equals(context.local(), v8_str("undefined"))
    6336             :             .FromJust());
    6337          30 :   CHECK(v8::Null(isolate)
    6338             :             ->TypeOf(isolate)
    6339             :             ->Equals(context.local(), v8_str("object"))
    6340             :             .FromJust());
    6341          30 :   CHECK(v8_str("str")
    6342             :             ->TypeOf(isolate)
    6343             :             ->Equals(context.local(), v8_str("string"))
    6344             :             .FromJust());
    6345          30 :   CHECK(v8_num(0.0)
    6346             :             ->TypeOf(isolate)
    6347             :             ->Equals(context.local(), v8_str("number"))
    6348             :             .FromJust());
    6349          30 :   CHECK(v8_num(1)
    6350             :             ->TypeOf(isolate)
    6351             :             ->Equals(context.local(), v8_str("number"))
    6352             :             .FromJust());
    6353          30 :   CHECK(v8::Object::New(isolate)
    6354             :             ->TypeOf(isolate)
    6355             :             ->Equals(context.local(), v8_str("object"))
    6356             :             .FromJust());
    6357          30 :   CHECK(v8::Boolean::New(isolate, true)
    6358             :             ->TypeOf(isolate)
    6359             :             ->Equals(context.local(), v8_str("boolean"))
    6360             :             .FromJust());
    6361          24 :   CHECK(fun->TypeOf(isolate)
    6362             :             ->Equals(context.local(), v8_str("function"))
    6363           6 :             .FromJust());
    6364           6 : }
    6365             : 
    6366       23724 : THREADED_TEST(InstanceOf) {
    6367           6 :   LocalContext env;
    6368          12 :   v8::HandleScope scope(env->GetIsolate());
    6369             :   CompileRun(
    6370             :       "var A = {};"
    6371             :       "var B = {};"
    6372             :       "var C = {};"
    6373             :       "B.__proto__ = A;"
    6374             :       "C.__proto__ = B;"
    6375             :       "function F() {}"
    6376             :       "F.prototype = A;"
    6377             :       "var G = { [Symbol.hasInstance] : null};"
    6378             :       "var H = { [Symbol.hasInstance] : () => { throw new Error(); } };"
    6379             :       "var J = { [Symbol.hasInstance] : () => true };"
    6380             :       "class K {}"
    6381             :       "var D = new K;"
    6382             :       "class L extends K {}"
    6383             :       "var E = new L");
    6384             : 
    6385           6 :   v8::Local<v8::Object> f = v8::Local<v8::Object>::Cast(CompileRun("F"));
    6386           6 :   v8::Local<v8::Object> g = v8::Local<v8::Object>::Cast(CompileRun("G"));
    6387           6 :   v8::Local<v8::Object> h = v8::Local<v8::Object>::Cast(CompileRun("H"));
    6388           6 :   v8::Local<v8::Object> j = v8::Local<v8::Object>::Cast(CompileRun("J"));
    6389           6 :   v8::Local<v8::Object> k = v8::Local<v8::Object>::Cast(CompileRun("K"));
    6390           6 :   v8::Local<v8::Object> l = v8::Local<v8::Object>::Cast(CompileRun("L"));
    6391             :   v8::Local<v8::Value> a = v8::Local<v8::Value>::Cast(CompileRun("A"));
    6392             :   v8::Local<v8::Value> b = v8::Local<v8::Value>::Cast(CompileRun("B"));
    6393             :   v8::Local<v8::Value> c = v8::Local<v8::Value>::Cast(CompileRun("C"));
    6394             :   v8::Local<v8::Value> d = v8::Local<v8::Value>::Cast(CompileRun("D"));
    6395             :   v8::Local<v8::Value> e = v8::Local<v8::Value>::Cast(CompileRun("E"));
    6396             : 
    6397          12 :   v8::TryCatch try_catch(env->GetIsolate());
    6398          12 :   CHECK(!a->InstanceOf(env.local(), f).ToChecked());
    6399          12 :   CHECK(b->InstanceOf(env.local(), f).ToChecked());
    6400          12 :   CHECK(c->InstanceOf(env.local(), f).ToChecked());
    6401          12 :   CHECK(!d->InstanceOf(env.local(), f).ToChecked());
    6402          12 :   CHECK(!e->InstanceOf(env.local(), f).ToChecked());
    6403           6 :   CHECK(!try_catch.HasCaught());
    6404             : 
    6405          12 :   CHECK(a->InstanceOf(env.local(), g).IsNothing());
    6406           6 :   CHECK(try_catch.HasCaught());
    6407           6 :   try_catch.Reset();
    6408             : 
    6409          12 :   CHECK(b->InstanceOf(env.local(), h).IsNothing());
    6410           6 :   CHECK(try_catch.HasCaught());
    6411           6 :   try_catch.Reset();
    6412             : 
    6413          18 :   CHECK(v8_num(1)->InstanceOf(env.local(), j).ToChecked());
    6414           6 :   CHECK(!try_catch.HasCaught());
    6415             : 
    6416          12 :   CHECK(d->InstanceOf(env.local(), k).ToChecked());
    6417          12 :   CHECK(e->InstanceOf(env.local(), k).ToChecked());
    6418          12 :   CHECK(!d->InstanceOf(env.local(), l).ToChecked());
    6419          12 :   CHECK(e->InstanceOf(env.local(), l).ToChecked());
    6420          12 :   CHECK(!try_catch.HasCaught());
    6421           6 : }
    6422             : 
    6423       23724 : THREADED_TEST(MultiRun) {
    6424           6 :   LocalContext context;
    6425          12 :   v8::HandleScope scope(context->GetIsolate());
    6426             :   Local<Script> script = v8_compile("x");
    6427          66 :   for (int i = 0; i < 10; i++) {
    6428          60 :     script->Run(context.local()).IsEmpty();
    6429           6 :   }
    6430           6 : }
    6431             : 
    6432             : 
    6433         204 : static void GetXValue(Local<Name> name,
    6434             :                       const v8::PropertyCallbackInfo<v8::Value>& info) {
    6435         204 :   ApiTestFuzzer::Fuzz();
    6436         816 :   CHECK(info.Data()
    6437             :             ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
    6438             :             .FromJust());
    6439         816 :   CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
    6440             :             .FromJust());
    6441             :   info.GetReturnValue().Set(name);
    6442         204 : }
    6443             : 
    6444             : 
    6445       23724 : THREADED_TEST(SimplePropertyRead) {
    6446           6 :   LocalContext context;
    6447           6 :   v8::Isolate* isolate = context->GetIsolate();
    6448          12 :   v8::HandleScope scope(isolate);
    6449           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6450          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6451          36 :   CHECK(context->Global()
    6452             :             ->Set(context.local(), v8_str("obj"),
    6453             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6454             :             .FromJust());
    6455             :   Local<Script> script = v8_compile("obj.x");
    6456          66 :   for (int i = 0; i < 10; i++) {
    6457          60 :     Local<Value> result = script->Run(context.local()).ToLocalChecked();
    6458         180 :     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    6459           6 :   }
    6460           6 : }
    6461             : 
    6462             : 
    6463       23724 : THREADED_TEST(DefinePropertyOnAPIAccessor) {
    6464           6 :   LocalContext context;
    6465           6 :   v8::Isolate* isolate = context->GetIsolate();
    6466          12 :   v8::HandleScope scope(isolate);
    6467           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6468          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6469          36 :   CHECK(context->Global()
    6470             :             ->Set(context.local(), v8_str("obj"),
    6471             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6472             :             .FromJust());
    6473             : 
    6474             :   // Uses getOwnPropertyDescriptor to check the configurable status
    6475             :   Local<Script> script_desc = v8_compile(
    6476             :       "var prop = Object.getOwnPropertyDescriptor( "
    6477             :       "obj, 'x');"
    6478             :       "prop.configurable;");
    6479           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6480          12 :   CHECK(result->BooleanValue(context.local()).FromJust());
    6481             : 
    6482             :   // Redefine get - but still configurable
    6483             :   Local<Script> script_define = v8_compile(
    6484             :       "var desc = { get: function(){return 42; },"
    6485             :       "            configurable: true };"
    6486             :       "Object.defineProperty(obj, 'x', desc);"
    6487             :       "obj.x");
    6488           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6489          12 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6490             : 
    6491             :   // Check that the accessor is still configurable
    6492           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6493          12 :   CHECK(result->BooleanValue(context.local()).FromJust());
    6494             : 
    6495             :   // Redefine to a non-configurable
    6496             :   script_define = v8_compile(
    6497             :       "var desc = { get: function(){return 43; },"
    6498             :       "             configurable: false };"
    6499             :       "Object.defineProperty(obj, 'x', desc);"
    6500             :       "obj.x");
    6501           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6502          12 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6503           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6504          12 :   CHECK(!result->BooleanValue(context.local()).FromJust());
    6505             : 
    6506             :   // Make sure that it is not possible to redefine again
    6507          12 :   v8::TryCatch try_catch(isolate);
    6508          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6509           6 :   CHECK(try_catch.HasCaught());
    6510          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6511           6 :   CHECK_EQ(0,
    6512           6 :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6513           6 : }
    6514             : 
    6515             : 
    6516       23724 : THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
    6517           6 :   v8::Isolate* isolate = CcTest::isolate();
    6518           6 :   v8::HandleScope scope(isolate);
    6519           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6520          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6521          12 :   LocalContext context;
    6522          36 :   CHECK(context->Global()
    6523             :             ->Set(context.local(), v8_str("obj"),
    6524             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6525             :             .FromJust());
    6526             : 
    6527             :   Local<Script> script_desc = v8_compile(
    6528             :       "var prop ="
    6529             :       "Object.getOwnPropertyDescriptor( "
    6530             :       "obj, 'x');"
    6531             :       "prop.configurable;");
    6532           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6533          12 :   CHECK(result->BooleanValue(context.local()).FromJust());
    6534             : 
    6535             :   Local<Script> script_define = v8_compile(
    6536             :       "var desc = {get: function(){return 42; },"
    6537             :       "            configurable: true };"
    6538             :       "Object.defineProperty(obj, 'x', desc);"
    6539             :       "obj.x");
    6540           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6541          12 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6542             : 
    6543           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6544          12 :   CHECK(result->BooleanValue(context.local()).FromJust());
    6545             : 
    6546             :   script_define = v8_compile(
    6547             :       "var desc = {get: function(){return 43; },"
    6548             :       "            configurable: false };"
    6549             :       "Object.defineProperty(obj, 'x', desc);"
    6550             :       "obj.x");
    6551           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6552          12 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6553             : 
    6554           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6555          12 :   CHECK(!result->BooleanValue(context.local()).FromJust());
    6556             : 
    6557          12 :   v8::TryCatch try_catch(isolate);
    6558          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6559           6 :   CHECK(try_catch.HasCaught());
    6560          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6561           6 :   CHECK_EQ(0,
    6562           6 :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6563           6 : }
    6564             : 
    6565             : 
    6566          72 : static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
    6567             :                                                char const* name) {
    6568             :   return v8::Local<v8::Object>::Cast(
    6569             :       (*context)
    6570             :           ->Global()
    6571         288 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
    6572         144 :           .ToLocalChecked());
    6573             : }
    6574             : 
    6575             : 
    6576       23724 : THREADED_TEST(DefineAPIAccessorOnObject) {
    6577           6 :   v8::Isolate* isolate = CcTest::isolate();
    6578           6 :   v8::HandleScope scope(isolate);
    6579           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6580          12 :   LocalContext context;
    6581             : 
    6582          42 :   CHECK(context->Global()
    6583             :             ->Set(context.local(), v8_str("obj1"),
    6584             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6585             :             .FromJust());
    6586             :   CompileRun("var obj2 = {};");
    6587             : 
    6588           6 :   CHECK(CompileRun("obj1.x")->IsUndefined());
    6589           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6590             : 
    6591          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6592             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6593             :                           v8_str("donut"))
    6594             :             .FromJust());
    6595             : 
    6596           6 :   ExpectString("obj1.x", "x");
    6597           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6598             : 
    6599          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6600             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6601             :                           v8_str("donut"))
    6602             :             .FromJust());
    6603             : 
    6604           6 :   ExpectString("obj1.x", "x");
    6605           6 :   ExpectString("obj2.x", "x");
    6606             : 
    6607             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6608             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6609             : 
    6610             :   CompileRun(
    6611             :       "Object.defineProperty(obj1, 'x',"
    6612             :       "{ get: function() { return 'y'; }, configurable: true })");
    6613             : 
    6614           6 :   ExpectString("obj1.x", "y");
    6615           6 :   ExpectString("obj2.x", "x");
    6616             : 
    6617             :   CompileRun(
    6618             :       "Object.defineProperty(obj2, 'x',"
    6619             :       "{ get: function() { return 'y'; }, configurable: true })");
    6620             : 
    6621           6 :   ExpectString("obj1.x", "y");
    6622           6 :   ExpectString("obj2.x", "y");
    6623             : 
    6624             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6625             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6626             : 
    6627          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6628             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6629             :                           v8_str("donut"))
    6630             :             .FromJust());
    6631          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6632             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6633             :                           v8_str("donut"))
    6634             :             .FromJust());
    6635             : 
    6636           6 :   ExpectString("obj1.x", "x");
    6637           6 :   ExpectString("obj2.x", "x");
    6638             : 
    6639             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6640             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6641             : 
    6642             :   // Define getters/setters, but now make them not configurable.
    6643             :   CompileRun(
    6644             :       "Object.defineProperty(obj1, 'x',"
    6645             :       "{ get: function() { return 'z'; }, configurable: false })");
    6646             :   CompileRun(
    6647             :       "Object.defineProperty(obj2, 'x',"
    6648             :       "{ get: function() { return 'z'; }, configurable: false })");
    6649             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6650             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6651             : 
    6652           6 :   ExpectString("obj1.x", "z");
    6653           6 :   ExpectString("obj2.x", "z");
    6654             : 
    6655          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6656             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6657             :                            v8_str("donut"))
    6658             :              .FromJust());
    6659          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6660             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6661             :                            v8_str("donut"))
    6662             :              .FromJust());
    6663             : 
    6664           6 :   ExpectString("obj1.x", "z");
    6665          12 :   ExpectString("obj2.x", "z");
    6666           6 : }
    6667             : 
    6668             : 
    6669       23724 : THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
    6670           6 :   v8::Isolate* isolate = CcTest::isolate();
    6671           6 :   v8::HandleScope scope(isolate);
    6672           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6673          12 :   LocalContext context;
    6674             : 
    6675          42 :   CHECK(context->Global()
    6676             :             ->Set(context.local(), v8_str("obj1"),
    6677             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6678             :             .FromJust());
    6679             :   CompileRun("var obj2 = {};");
    6680             : 
    6681          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6682             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6683             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6684             :             .FromJust());
    6685          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6686             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6687             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6688             :             .FromJust());
    6689             : 
    6690           6 :   ExpectString("obj1.x", "x");
    6691           6 :   ExpectString("obj2.x", "x");
    6692             : 
    6693             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6694             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6695             : 
    6696          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6697             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6698             :                            v8_str("donut"))
    6699             :              .FromJust());
    6700          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6701             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6702             :                            v8_str("donut"))
    6703             :              .FromJust());
    6704             : 
    6705             :   {
    6706           6 :     v8::TryCatch try_catch(isolate);
    6707             :     CompileRun(
    6708             :         "Object.defineProperty(obj1, 'x',"
    6709             :         "{get: function() { return 'func'; }})");
    6710           6 :     CHECK(try_catch.HasCaught());
    6711          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6712           6 :     CHECK_EQ(
    6713           6 :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6714             :   }
    6715             :   {
    6716           6 :     v8::TryCatch try_catch(isolate);
    6717             :     CompileRun(
    6718             :         "Object.defineProperty(obj2, 'x',"
    6719             :         "{get: function() { return 'func'; }})");
    6720           6 :     CHECK(try_catch.HasCaught());
    6721          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6722           6 :     CHECK_EQ(
    6723           6 :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6724           6 :   }
    6725           6 : }
    6726             : 
    6727             : 
    6728          24 : static void Get239Value(Local<Name> name,
    6729             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    6730          24 :   ApiTestFuzzer::Fuzz();
    6731          96 :   CHECK(info.Data()
    6732             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
    6733             :             .FromJust());
    6734          96 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
    6735             :             .FromJust());
    6736             :   info.GetReturnValue().Set(name);
    6737          24 : }
    6738             : 
    6739             : 
    6740       23724 : THREADED_TEST(ElementAPIAccessor) {
    6741           6 :   v8::Isolate* isolate = CcTest::isolate();
    6742           6 :   v8::HandleScope scope(isolate);
    6743           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6744          12 :   LocalContext context;
    6745             : 
    6746          42 :   CHECK(context->Global()
    6747             :             ->Set(context.local(), v8_str("obj1"),
    6748             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6749             :             .FromJust());
    6750             :   CompileRun("var obj2 = {};");
    6751             : 
    6752          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6753             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6754             :                           v8_str("donut"))
    6755             :             .FromJust());
    6756          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6757             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6758             :                           v8_str("donut"))
    6759             :             .FromJust());
    6760             : 
    6761           6 :   ExpectString("obj1[239]", "239");
    6762           6 :   ExpectString("obj2[239]", "239");
    6763           6 :   ExpectString("obj1['239']", "239");
    6764          12 :   ExpectString("obj2['239']", "239");
    6765           6 : }
    6766             : 
    6767             : 
    6768       23718 : v8::Persistent<Value> xValue;
    6769             : 
    6770             : 
    6771         120 : static void SetXValue(Local<Name> name, Local<Value> value,
    6772             :                       const v8::PropertyCallbackInfo<void>& info) {
    6773         120 :   Local<Context> context = info.GetIsolate()->GetCurrentContext();
    6774         240 :   CHECK(value->Equals(context, v8_num(4)).FromJust());
    6775         360 :   CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
    6776         360 :   CHECK(name->Equals(context, v8_str("x")).FromJust());
    6777         120 :   CHECK(xValue.IsEmpty());
    6778             :   xValue.Reset(info.GetIsolate(), value);
    6779         120 : }
    6780             : 
    6781             : 
    6782       23724 : THREADED_TEST(SimplePropertyWrite) {
    6783           6 :   v8::Isolate* isolate = CcTest::isolate();
    6784           6 :   v8::HandleScope scope(isolate);
    6785           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6786          18 :   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
    6787          12 :   LocalContext context;
    6788          36 :   CHECK(context->Global()
    6789             :             ->Set(context.local(), v8_str("obj"),
    6790             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6791             :             .FromJust());
    6792             :   Local<Script> script = v8_compile("obj.x = 4");
    6793          66 :   for (int i = 0; i < 10; i++) {
    6794          60 :     CHECK(xValue.IsEmpty());
    6795          60 :     script->Run(context.local()).ToLocalChecked();
    6796         240 :     CHECK(v8_num(4)
    6797             :               ->Equals(context.local(),
    6798             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6799             :               .FromJust());
    6800             :     xValue.Reset();
    6801           6 :   }
    6802           6 : }
    6803             : 
    6804             : 
    6805       23724 : THREADED_TEST(SetterOnly) {
    6806           6 :   v8::Isolate* isolate = CcTest::isolate();
    6807           6 :   v8::HandleScope scope(isolate);
    6808           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6809          18 :   templ->SetAccessor(v8_str("x"), nullptr, SetXValue, v8_str("donut"));
    6810          12 :   LocalContext context;
    6811          36 :   CHECK(context->Global()
    6812             :             ->Set(context.local(), v8_str("obj"),
    6813             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6814             :             .FromJust());
    6815             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    6816          66 :   for (int i = 0; i < 10; i++) {
    6817          60 :     CHECK(xValue.IsEmpty());
    6818          60 :     script->Run(context.local()).ToLocalChecked();
    6819         240 :     CHECK(v8_num(4)
    6820             :               ->Equals(context.local(),
    6821             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6822             :               .FromJust());
    6823             :     xValue.Reset();
    6824           6 :   }
    6825           6 : }
    6826             : 
    6827             : 
    6828       23724 : THREADED_TEST(NoAccessors) {
    6829           6 :   v8::Isolate* isolate = CcTest::isolate();
    6830           6 :   v8::HandleScope scope(isolate);
    6831           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6832             :   templ->SetAccessor(v8_str("x"),
    6833             :                      static_cast<v8::AccessorGetterCallback>(nullptr), nullptr,
    6834          12 :                      v8_str("donut"));
    6835          12 :   LocalContext context;
    6836          36 :   CHECK(context->Global()
    6837             :             ->Set(context.local(), v8_str("obj"),
    6838             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6839             :             .FromJust());
    6840             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    6841          66 :   for (int i = 0; i < 10; i++) {
    6842          60 :     script->Run(context.local()).ToLocalChecked();
    6843           6 :   }
    6844           6 : }
    6845             : 
    6846             : 
    6847       23724 : THREADED_TEST(MultiContexts) {
    6848           6 :   v8::Isolate* isolate = CcTest::isolate();
    6849           6 :   v8::HandleScope scope(isolate);
    6850           6 :   v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6851             :   templ->Set(v8_str("dummy"),
    6852          18 :              v8::FunctionTemplate::New(isolate, DummyCallHandler));
    6853             : 
    6854           6 :   Local<String> password = v8_str("Password");
    6855             : 
    6856             :   // Create an environment
    6857          12 :   LocalContext context0(0, templ);
    6858           6 :   context0->SetSecurityToken(password);
    6859           6 :   v8::Local<v8::Object> global0 = context0->Global();
    6860          18 :   CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
    6861             :             .FromJust());
    6862          24 :   CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
    6863             :                      .ToLocalChecked()
    6864             :                      ->Int32Value(context0.local())
    6865             :                      .FromJust());
    6866             : 
    6867             :   // Create an independent environment
    6868          12 :   LocalContext context1(0, templ);
    6869           6 :   context1->SetSecurityToken(password);
    6870           6 :   v8::Local<v8::Object> global1 = context1->Global();
    6871          18 :   CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
    6872             :             .FromJust());
    6873          12 :   CHECK(!global0->Equals(context1.local(), global1).FromJust());
    6874          24 :   CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
    6875             :                      .ToLocalChecked()
    6876             :                      ->Int32Value(context0.local())
    6877             :                      .FromJust());
    6878          24 :   CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
    6879             :                      .ToLocalChecked()
    6880             :                      ->Int32Value(context1.local())
    6881             :                      .FromJust());
    6882             : 
    6883             :   // Now create a new context with the old global
    6884          12 :   LocalContext context2(0, templ, global1);
    6885           6 :   context2->SetSecurityToken(password);
    6886           6 :   v8::Local<v8::Object> global2 = context2->Global();
    6887          12 :   CHECK(global1->Equals(context2.local(), global2).FromJust());
    6888          24 :   CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
    6889             :                   .ToLocalChecked()
    6890             :                   ->Int32Value(context1.local())
    6891             :                   .FromJust());
    6892          24 :   CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
    6893             :                   .ToLocalChecked()
    6894             :                   ->Int32Value(context2.local())
    6895           6 :                   .FromJust());
    6896           6 : }
    6897             : 
    6898             : 
    6899       23724 : THREADED_TEST(FunctionPrototypeAcrossContexts) {
    6900             :   // Make sure that functions created by cloning boilerplates cannot
    6901             :   // communicate through their __proto__ field.
    6902             : 
    6903           6 :   v8::HandleScope scope(CcTest::isolate());
    6904             : 
    6905          12 :   LocalContext env0;
    6906           6 :   v8::Local<v8::Object> global0 = env0->Global();
    6907          18 :   v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
    6908           6 :                                       .ToLocalChecked()
    6909             :                                       .As<v8::Object>();
    6910             :   v8::Local<v8::Object> tostring0 =
    6911          18 :       object0->Get(env0.local(), v8_str("toString"))
    6912           6 :           .ToLocalChecked()
    6913             :           .As<v8::Object>();
    6914             :   v8::Local<v8::Object> proto0 =
    6915          18 :       tostring0->Get(env0.local(), v8_str("__proto__"))
    6916           6 :           .ToLocalChecked()
    6917             :           .As<v8::Object>();
    6918          18 :   CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
    6919             : 
    6920          12 :   LocalContext env1;
    6921           6 :   v8::Local<v8::Object> global1 = env1->Global();
    6922          18 :   v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
    6923           6 :                                       .ToLocalChecked()
    6924             :                                       .As<v8::Object>();
    6925             :   v8::Local<v8::Object> tostring1 =
    6926          18 :       object1->Get(env1.local(), v8_str("toString"))
    6927           6 :           .ToLocalChecked()
    6928             :           .As<v8::Object>();
    6929             :   v8::Local<v8::Object> proto1 =
    6930          18 :       tostring1->Get(env1.local(), v8_str("__proto__"))
    6931           6 :           .ToLocalChecked()
    6932             :           .As<v8::Object>();
    6933          24 :   CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
    6934           6 : }
    6935             : 
    6936             : 
    6937       23724 : THREADED_TEST(Regress892105) {
    6938             :   // Make sure that object and array literals created by cloning
    6939             :   // boilerplates cannot communicate through their __proto__
    6940             :   // field. This is rather difficult to check, but we try to add stuff
    6941             :   // to Object.prototype and Array.prototype and create a new
    6942             :   // environment. This should succeed.
    6943             : 
    6944           6 :   v8::HandleScope scope(CcTest::isolate());
    6945             : 
    6946             :   Local<String> source = v8_str(
    6947             :       "Object.prototype.obj = 1234;"
    6948             :       "Array.prototype.arr = 4567;"
    6949           6 :       "8901");
    6950             : 
    6951          12 :   LocalContext env0;
    6952           6 :   Local<Script> script0 = v8_compile(source);
    6953          24 :   CHECK_EQ(8901.0, script0->Run(env0.local())
    6954             :                        .ToLocalChecked()
    6955             :                        ->NumberValue(env0.local())
    6956             :                        .FromJust());
    6957             : 
    6958          12 :   LocalContext env1;
    6959           6 :   Local<Script> script1 = v8_compile(source);
    6960          24 :   CHECK_EQ(8901.0, script1->Run(env1.local())
    6961             :                        .ToLocalChecked()
    6962             :                        ->NumberValue(env1.local())
    6963           6 :                        .FromJust());
    6964           6 : }
    6965             : 
    6966          60 : static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6967             :   args.GetReturnValue().Set(args.This());
    6968          30 : }
    6969             : 
    6970       23724 : THREADED_TEST(UndetectableObject) {
    6971           6 :   LocalContext env;
    6972          12 :   v8::HandleScope scope(env->GetIsolate());
    6973             : 
    6974             :   Local<v8::FunctionTemplate> desc =
    6975           6 :       v8::FunctionTemplate::New(env->GetIsolate());
    6976          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    6977          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    6978             : 
    6979           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    6980           6 :                               .ToLocalChecked()
    6981           6 :                               ->NewInstance(env.local())
    6982             :                               .ToLocalChecked();
    6983          30 :   CHECK(
    6984             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    6985             : 
    6986           6 :   ExpectString("undetectable.toString()", "[object Object]");
    6987           6 :   ExpectString("typeof undetectable", "undefined");
    6988           6 :   ExpectString("typeof(undetectable)", "undefined");
    6989           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
    6990           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
    6991           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
    6992           6 :   ExpectBoolean("!undetectable", true);
    6993             : 
    6994           6 :   ExpectObject("true&&undetectable", obj);
    6995           6 :   ExpectBoolean("false&&undetectable", false);
    6996           6 :   ExpectBoolean("true||undetectable", true);
    6997           6 :   ExpectObject("false||undetectable", obj);
    6998             : 
    6999           6 :   ExpectObject("undetectable&&true", obj);
    7000           6 :   ExpectObject("undetectable&&false", obj);
    7001           6 :   ExpectBoolean("undetectable||true", true);
    7002           6 :   ExpectBoolean("undetectable||false", false);
    7003             : 
    7004           6 :   ExpectBoolean("undetectable==null", true);
    7005           6 :   ExpectBoolean("null==undetectable", true);
    7006           6 :   ExpectBoolean("undetectable==undefined", true);
    7007           6 :   ExpectBoolean("undefined==undetectable", true);
    7008           6 :   ExpectBoolean("undetectable==undetectable", true);
    7009             : 
    7010             : 
    7011           6 :   ExpectBoolean("undetectable===null", false);
    7012           6 :   ExpectBoolean("null===undetectable", false);
    7013           6 :   ExpectBoolean("undetectable===undefined", false);
    7014           6 :   ExpectBoolean("undefined===undetectable", false);
    7015          12 :   ExpectBoolean("undetectable===undetectable", true);
    7016           6 : }
    7017             : 
    7018             : 
    7019       23724 : THREADED_TEST(VoidLiteral) {
    7020           6 :   LocalContext env;
    7021           6 :   v8::Isolate* isolate = env->GetIsolate();
    7022          12 :   v8::HandleScope scope(isolate);
    7023             : 
    7024           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7025          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7026          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7027             : 
    7028           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7029           6 :                               .ToLocalChecked()
    7030           6 :                               ->NewInstance(env.local())
    7031             :                               .ToLocalChecked();
    7032          30 :   CHECK(
    7033             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7034             : 
    7035           6 :   ExpectBoolean("undefined == void 0", true);
    7036           6 :   ExpectBoolean("undetectable == void 0", true);
    7037           6 :   ExpectBoolean("null == void 0", true);
    7038           6 :   ExpectBoolean("undefined === void 0", true);
    7039           6 :   ExpectBoolean("undetectable === void 0", false);
    7040           6 :   ExpectBoolean("null === void 0", false);
    7041             : 
    7042           6 :   ExpectBoolean("void 0 == undefined", true);
    7043           6 :   ExpectBoolean("void 0 == undetectable", true);
    7044           6 :   ExpectBoolean("void 0 == null", true);
    7045           6 :   ExpectBoolean("void 0 === undefined", true);
    7046           6 :   ExpectBoolean("void 0 === undetectable", false);
    7047           6 :   ExpectBoolean("void 0 === null", false);
    7048             : 
    7049             :   ExpectString(
    7050             :       "(function() {"
    7051             :       "  try {"
    7052             :       "    return x === void 0;"
    7053             :       "  } catch(e) {"
    7054             :       "    return e.toString();"
    7055             :       "  }"
    7056             :       "})()",
    7057           6 :       "ReferenceError: x is not defined");
    7058             :   ExpectString(
    7059             :       "(function() {"
    7060             :       "  try {"
    7061             :       "    return void 0 === x;"
    7062             :       "  } catch(e) {"
    7063             :       "    return e.toString();"
    7064             :       "  }"
    7065             :       "})()",
    7066          12 :       "ReferenceError: x is not defined");
    7067           6 : }
    7068             : 
    7069             : 
    7070       23724 : THREADED_TEST(ExtensibleOnUndetectable) {
    7071           6 :   LocalContext env;
    7072           6 :   v8::Isolate* isolate = env->GetIsolate();
    7073          12 :   v8::HandleScope scope(isolate);
    7074             : 
    7075           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7076          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7077          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7078             : 
    7079           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7080           6 :                               .ToLocalChecked()
    7081           6 :                               ->NewInstance(env.local())
    7082             :                               .ToLocalChecked();
    7083          30 :   CHECK(
    7084             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7085             : 
    7086             :   Local<String> source = v8_str(
    7087             :       "undetectable.x = 42;"
    7088           6 :       "undetectable.x");
    7089             : 
    7090           6 :   Local<Script> script = v8_compile(source);
    7091             : 
    7092          24 :   CHECK(v8::Integer::New(isolate, 42)
    7093             :             ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
    7094             :             .FromJust());
    7095             : 
    7096           6 :   ExpectBoolean("Object.isExtensible(undetectable)", true);
    7097             : 
    7098           6 :   source = v8_str("Object.preventExtensions(undetectable);");
    7099           6 :   script = v8_compile(source);
    7100           6 :   script->Run(env.local()).ToLocalChecked();
    7101           6 :   ExpectBoolean("Object.isExtensible(undetectable)", false);
    7102             : 
    7103           6 :   source = v8_str("undetectable.y = 2000;");
    7104           6 :   script = v8_compile(source);
    7105           6 :   script->Run(env.local()).ToLocalChecked();
    7106          12 :   ExpectBoolean("undetectable.y == undefined", true);
    7107           6 : }
    7108             : 
    7109             : 
    7110             : // The point of this test is type checking. We run it only so compilers
    7111             : // don't complain about an unused function.
    7112       23723 : TEST(PersistentHandles) {
    7113           5 :   LocalContext env;
    7114           5 :   v8::Isolate* isolate = CcTest::isolate();
    7115          10 :   v8::HandleScope scope(isolate);
    7116           5 :   Local<String> str = v8_str("foo");
    7117             :   v8::Persistent<String> p_str(isolate, str);
    7118             :   p_str.Reset();
    7119             :   Local<Script> scr = v8_compile("");
    7120             :   v8::Persistent<Script> p_scr(isolate, scr);
    7121             :   p_scr.Reset();
    7122           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7123             :   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
    7124           5 :   p_templ.Reset();
    7125           5 : }
    7126             : 
    7127             : 
    7128           6 : static void HandleLogDelegator(
    7129             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7130           6 :   ApiTestFuzzer::Fuzz();
    7131           6 : }
    7132             : 
    7133             : 
    7134       23724 : THREADED_TEST(GlobalObjectTemplate) {
    7135           6 :   v8::Isolate* isolate = CcTest::isolate();
    7136           6 :   v8::HandleScope handle_scope(isolate);
    7137           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
    7138             :   global_template->Set(v8_str("JSNI_Log"),
    7139          18 :                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
    7140           6 :   v8::Local<Context> context = Context::New(isolate, 0, global_template);
    7141             :   Context::Scope context_scope(context);
    7142           6 :   CompileRun("JSNI_Log('LOG')");
    7143           6 : }
    7144             : 
    7145             : 
    7146             : static const char* kSimpleExtensionSource =
    7147             :     "function Foo() {"
    7148             :     "  return 4;"
    7149             :     "}";
    7150             : 
    7151             : 
    7152       23723 : TEST(SimpleExtensions) {
    7153           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7154           5 :   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
    7155           5 :   const char* extension_names[] = {"simpletest"};
    7156             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7157           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7158             :   Context::Scope lock(context);
    7159             :   v8::Local<Value> result = CompileRun("Foo()");
    7160          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7161           5 :             .FromJust());
    7162           5 : }
    7163             : 
    7164             : 
    7165             : static const char* kStackTraceFromExtensionSource =
    7166             :     "function foo() {"
    7167             :     "  throw new Error();"
    7168             :     "}"
    7169             :     "function bar() {"
    7170             :     "  foo();"
    7171             :     "}";
    7172             : 
    7173             : 
    7174       23723 : TEST(StackTraceInExtension) {
    7175           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7176             :   v8::RegisterExtension(
    7177           5 :       new Extension("stacktracetest", kStackTraceFromExtensionSource));
    7178           5 :   const char* extension_names[] = {"stacktracetest"};
    7179             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7180           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7181             :   Context::Scope lock(context);
    7182             :   CompileRun(
    7183             :       "function user() { bar(); }"
    7184             :       "var error;"
    7185             :       "try{ user(); } catch (e) { error = e; }");
    7186           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
    7187           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
    7188          10 :   CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
    7189           5 : }
    7190             : 
    7191             : 
    7192       23723 : TEST(NullExtensions) {
    7193           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7194           5 :   v8::RegisterExtension(new Extension("nulltest", nullptr));
    7195           5 :   const char* extension_names[] = {"nulltest"};
    7196             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7197           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7198             :   Context::Scope lock(context);
    7199             :   v8::Local<Value> result = CompileRun("1+3");
    7200          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7201           5 :             .FromJust());
    7202           5 : }
    7203             : 
    7204             : static const char* kEmbeddedExtensionSource =
    7205             :     "function Ret54321(){return 54321;}~~@@$"
    7206             :     "$%% THIS IS A SERIES OF NON-nullptr-TERMINATED STRINGS.";
    7207             : static const int kEmbeddedExtensionSourceValidLen = 34;
    7208             : 
    7209             : 
    7210       23723 : TEST(ExtensionMissingSourceLength) {
    7211           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7212             :   v8::RegisterExtension(
    7213           5 :       new Extension("srclentest_fail", kEmbeddedExtensionSource));
    7214           5 :   const char* extension_names[] = {"srclentest_fail"};
    7215             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7216           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7217           5 :   CHECK_NULL(*context);
    7218           5 : }
    7219             : 
    7220             : 
    7221       23723 : TEST(ExtensionWithSourceLength) {
    7222          20 :   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
    7223             :        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
    7224          15 :     v8::HandleScope handle_scope(CcTest::isolate());
    7225             :     i::ScopedVector<char> extension_name(32);
    7226          15 :     i::SNPrintF(extension_name, "ext #%d", source_len);
    7227             :     v8::RegisterExtension(new Extension(
    7228          15 :         extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
    7229          15 :     const char* extension_names[1] = {extension_name.start()};
    7230             :     v8::ExtensionConfiguration extensions(1, extension_names);
    7231          15 :     v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7232          15 :     if (source_len == kEmbeddedExtensionSourceValidLen) {
    7233             :       Context::Scope lock(context);
    7234           5 :       v8::Local<Value> result = CompileRun("Ret54321()");
    7235          15 :       CHECK(v8::Integer::New(CcTest::isolate(), 54321)
    7236             :                 ->Equals(context, result)
    7237             :                 .FromJust());
    7238             :     } else {
    7239             :       // Anything but exactly the right length should fail to compile.
    7240          10 :       CHECK_NULL(*context);
    7241             :     }
    7242          15 :   }
    7243           5 : }
    7244             : 
    7245             : 
    7246             : static const char* kEvalExtensionSource1 =
    7247             :     "function UseEval1() {"
    7248             :     "  var x = 42;"
    7249             :     "  return eval('x');"
    7250             :     "}";
    7251             : 
    7252             : 
    7253             : static const char* kEvalExtensionSource2 =
    7254             :     "(function() {"
    7255             :     "  var x = 42;"
    7256             :     "  function e() {"
    7257             :     "    return eval('x');"
    7258             :     "  }"
    7259             :     "  this.UseEval2 = e;"
    7260             :     "})()";
    7261             : 
    7262             : 
    7263       23723 : TEST(UseEvalFromExtension) {
    7264           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7265           5 :   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
    7266           5 :   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
    7267           5 :   const char* extension_names[] = {"evaltest1", "evaltest2"};
    7268             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7269           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7270             :   Context::Scope lock(context);
    7271             :   v8::Local<Value> result = CompileRun("UseEval1()");
    7272          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7273             :             .FromJust());
    7274             :   result = CompileRun("UseEval2()");
    7275          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7276           5 :             .FromJust());
    7277           5 : }
    7278             : 
    7279             : 
    7280             : static const char* kWithExtensionSource1 =
    7281             :     "function UseWith1() {"
    7282             :     "  var x = 42;"
    7283             :     "  with({x:87}) { return x; }"
    7284             :     "}";
    7285             : 
    7286             : 
    7287             : static const char* kWithExtensionSource2 =
    7288             :     "(function() {"
    7289             :     "  var x = 42;"
    7290             :     "  function e() {"
    7291             :     "    with ({x:87}) { return x; }"
    7292             :     "  }"
    7293             :     "  this.UseWith2 = e;"
    7294             :     "})()";
    7295             : 
    7296             : 
    7297       23723 : TEST(UseWithFromExtension) {
    7298           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7299           5 :   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
    7300           5 :   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
    7301           5 :   const char* extension_names[] = {"withtest1", "withtest2"};
    7302             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7303           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7304             :   Context::Scope lock(context);
    7305             :   v8::Local<Value> result = CompileRun("UseWith1()");
    7306          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7307             :             .FromJust());
    7308             :   result = CompileRun("UseWith2()");
    7309          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7310           5 :             .FromJust());
    7311           5 : }
    7312             : 
    7313             : 
    7314       23723 : TEST(AutoExtensions) {
    7315           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7316           5 :   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
    7317             :   extension->set_auto_enable(true);
    7318           5 :   v8::RegisterExtension(extension);
    7319           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
    7320             :   Context::Scope lock(context);
    7321             :   v8::Local<Value> result = CompileRun("Foo()");
    7322          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7323           5 :             .FromJust());
    7324           5 : }
    7325             : 
    7326             : 
    7327             : static const char* kSyntaxErrorInExtensionSource = "[";
    7328             : 
    7329             : 
    7330             : // Test that a syntax error in an extension does not cause a fatal
    7331             : // error but results in an empty context.
    7332       23723 : TEST(SyntaxErrorExtensions) {
    7333           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7334             :   v8::RegisterExtension(
    7335           5 :       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
    7336           5 :   const char* extension_names[] = {"syntaxerror"};
    7337             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7338           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7339           5 :   CHECK(context.IsEmpty());
    7340           5 : }
    7341             : 
    7342             : 
    7343             : static const char* kExceptionInExtensionSource = "throw 42";
    7344             : 
    7345             : 
    7346             : // Test that an exception when installing an extension does not cause
    7347             : // a fatal error but results in an empty context.
    7348       23723 : TEST(ExceptionExtensions) {
    7349           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7350             :   v8::RegisterExtension(
    7351           5 :       new Extension("exception", kExceptionInExtensionSource));
    7352           5 :   const char* extension_names[] = {"exception"};
    7353             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7354           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7355           5 :   CHECK(context.IsEmpty());
    7356           5 : }
    7357             : 
    7358             : static const char* kNativeCallInExtensionSource =
    7359             :     "function call_runtime_last_index_of(x) {"
    7360             :     "  return %StringLastIndexOf(x, 'bob');"
    7361             :     "}";
    7362             : 
    7363             : static const char* kNativeCallTest =
    7364             :     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
    7365             : 
    7366             : // Test that a native runtime calls are supported in extensions.
    7367       23723 : TEST(NativeCallInExtensions) {
    7368           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7369             :   v8::RegisterExtension(
    7370           5 :       new Extension("nativecall", kNativeCallInExtensionSource));
    7371           5 :   const char* extension_names[] = {"nativecall"};
    7372             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7373           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7374             :   Context::Scope lock(context);
    7375           5 :   v8::Local<Value> result = CompileRun(kNativeCallTest);
    7376          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 24))
    7377           5 :             .FromJust());
    7378           5 : }
    7379             : 
    7380             : 
    7381           0 : class NativeFunctionExtension : public Extension {
    7382             :  public:
    7383             :   NativeFunctionExtension(const char* name, const char* source,
    7384             :                           v8::FunctionCallback fun = &Echo)
    7385          15 :       : Extension(name, source), function_(fun) {}
    7386             : 
    7387           5 :   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7388             :       v8::Isolate* isolate, v8::Local<v8::String> name) {
    7389           5 :     return v8::FunctionTemplate::New(isolate, function_);
    7390             :   }
    7391             : 
    7392          10 :   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7393           5 :     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
    7394           5 :   }
    7395             : 
    7396             :  private:
    7397             :   v8::FunctionCallback function_;
    7398             : };
    7399             : 
    7400             : 
    7401       23723 : TEST(NativeFunctionDeclaration) {
    7402           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7403             :   const char* name = "nativedecl";
    7404             :   v8::RegisterExtension(
    7405          10 :       new NativeFunctionExtension(name, "native function foo();"));
    7406           5 :   const char* extension_names[] = {name};
    7407             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7408           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7409             :   Context::Scope lock(context);
    7410             :   v8::Local<Value> result = CompileRun("foo(42);");
    7411          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7412           5 :             .FromJust());
    7413           5 : }
    7414             : 
    7415             : 
    7416       23723 : TEST(NativeFunctionDeclarationError) {
    7417           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7418             :   const char* name = "nativedeclerr";
    7419             :   // Syntax error in extension code.
    7420             :   v8::RegisterExtension(
    7421          10 :       new NativeFunctionExtension(name, "native\nfunction foo();"));
    7422           5 :   const char* extension_names[] = {name};
    7423             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7424           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7425           5 :   CHECK(context.IsEmpty());
    7426           5 : }
    7427             : 
    7428             : 
    7429       23723 : TEST(NativeFunctionDeclarationErrorEscape) {
    7430           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7431             :   const char* name = "nativedeclerresc";
    7432             :   // Syntax error in extension code - escape code in "native" means that
    7433             :   // it's not treated as a keyword.
    7434             :   v8::RegisterExtension(
    7435          10 :       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
    7436           5 :   const char* extension_names[] = {name};
    7437             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7438           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7439           5 :   CHECK(context.IsEmpty());
    7440           5 : }
    7441             : 
    7442             : 
    7443          30 : static void CheckDependencies(const char* name, const char* expected) {
    7444          30 :   v8::HandleScope handle_scope(CcTest::isolate());
    7445             :   v8::ExtensionConfiguration config(1, &name);
    7446          60 :   LocalContext context(&config);
    7447         210 :   CHECK(
    7448             :       v8_str(expected)
    7449             :           ->Equals(context.local(), context->Global()
    7450             :                                         ->Get(context.local(), v8_str("loaded"))
    7451             :                                         .ToLocalChecked())
    7452          30 :           .FromJust());
    7453          30 : }
    7454             : 
    7455             : 
    7456             : /*
    7457             :  * Configuration:
    7458             :  *
    7459             :  *     /-- B <--\
    7460             :  * A <-          -- D <-- E
    7461             :  *     \-- C <--/
    7462             :  */
    7463       23724 : THREADED_TEST(ExtensionDependency) {
    7464             :   static const char* kEDeps[] = {"D"};
    7465           6 :   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
    7466             :   static const char* kDDeps[] = {"B", "C"};
    7467           6 :   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
    7468             :   static const char* kBCDeps[] = {"A"};
    7469           6 :   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
    7470           6 :   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
    7471           6 :   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
    7472           6 :   CheckDependencies("A", "undefinedA");
    7473           6 :   CheckDependencies("B", "undefinedAB");
    7474           6 :   CheckDependencies("C", "undefinedAC");
    7475           6 :   CheckDependencies("D", "undefinedABCD");
    7476           6 :   CheckDependencies("E", "undefinedABCDE");
    7477           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7478             :   static const char* exts[2] = {"C", "E"};
    7479             :   v8::ExtensionConfiguration config(2, exts);
    7480          12 :   LocalContext context(&config);
    7481          42 :   CHECK(
    7482             :       v8_str("undefinedACBDE")
    7483             :           ->Equals(context.local(), context->Global()
    7484             :                                         ->Get(context.local(), v8_str("loaded"))
    7485             :                                         .ToLocalChecked())
    7486           6 :           .FromJust());
    7487           6 : }
    7488             : 
    7489             : 
    7490             : static const char* kExtensionTestScript =
    7491             :     "native function A();"
    7492             :     "native function B();"
    7493             :     "native function C();"
    7494             :     "function Foo(i) {"
    7495             :     "  if (i == 0) return A();"
    7496             :     "  if (i == 1) return B();"
    7497             :     "  if (i == 2) return C();"
    7498             :     "}";
    7499             : 
    7500             : 
    7501         738 : static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7502         198 :   ApiTestFuzzer::Fuzz();
    7503         198 :   if (args.IsConstructCall()) {
    7504         720 :     CHECK(args.This()
    7505             :               ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
    7506             :                     args.Data())
    7507             :               .FromJust());
    7508             :     args.GetReturnValue().SetNull();
    7509         378 :     return;
    7510             :   }
    7511             :   args.GetReturnValue().Set(args.Data());
    7512             : }
    7513             : 
    7514             : 
    7515           0 : class FunctionExtension : public Extension {
    7516             :  public:
    7517          12 :   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
    7518             :   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7519             :       v8::Isolate* isolate, v8::Local<String> name);
    7520             : };
    7521             : 
    7522             : 
    7523             : static int lookup_count = 0;
    7524          33 : v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
    7525             :     v8::Isolate* isolate, v8::Local<String> name) {
    7526          33 :   lookup_count++;
    7527          99 :   if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
    7528             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7529          22 :                                      v8::Integer::New(isolate, 8));
    7530          66 :   } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
    7531          44 :                  .FromJust()) {
    7532             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7533          22 :                                      v8::Integer::New(isolate, 7));
    7534          33 :   } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
    7535          22 :                  .FromJust()) {
    7536             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7537          22 :                                      v8::Integer::New(isolate, 6));
    7538             :   } else {
    7539           0 :     return v8::Local<v8::FunctionTemplate>();
    7540             :   }
    7541             : }
    7542             : 
    7543             : 
    7544       23724 : THREADED_TEST(FunctionLookup) {
    7545           6 :   v8::RegisterExtension(new FunctionExtension());
    7546           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7547             :   static const char* exts[1] = {"functiontest"};
    7548             :   v8::ExtensionConfiguration config(1, exts);
    7549          12 :   LocalContext context(&config);
    7550           6 :   CHECK_EQ(3, lookup_count);
    7551          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7552             :             ->Equals(context.local(), CompileRun("Foo(0)"))
    7553             :             .FromJust());
    7554          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7555             :             ->Equals(context.local(), CompileRun("Foo(1)"))
    7556             :             .FromJust());
    7557          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7558             :             ->Equals(context.local(), CompileRun("Foo(2)"))
    7559           6 :             .FromJust());
    7560           6 : }
    7561             : 
    7562             : 
    7563       23724 : THREADED_TEST(NativeFunctionConstructCall) {
    7564           6 :   v8::RegisterExtension(new FunctionExtension());
    7565           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7566             :   static const char* exts[1] = {"functiontest"};
    7567             :   v8::ExtensionConfiguration config(1, exts);
    7568          12 :   LocalContext context(&config);
    7569          66 :   for (int i = 0; i < 10; i++) {
    7570             :     // Run a few times to ensure that allocation of objects doesn't
    7571             :     // change behavior of a constructor function.
    7572         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7573             :               ->Equals(context.local(), CompileRun("(new A()).data"))
    7574             :               .FromJust());
    7575         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7576             :               ->Equals(context.local(), CompileRun("(new B()).data"))
    7577             :               .FromJust());
    7578         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7579             :               ->Equals(context.local(), CompileRun("(new C()).data"))
    7580             :               .FromJust());
    7581           6 :   }
    7582           6 : }
    7583             : 
    7584             : 
    7585             : static const char* last_location;
    7586             : static const char* last_message;
    7587          10 : void StoringErrorCallback(const char* location, const char* message) {
    7588          10 :   if (last_location == nullptr) {
    7589          10 :     last_location = location;
    7590          10 :     last_message = message;
    7591             :   }
    7592          10 : }
    7593             : 
    7594             : 
    7595             : // ErrorReporting creates a circular extensions configuration and
    7596             : // tests that the fatal error handler gets called.  This renders V8
    7597             : // unusable and therefore this test cannot be run in parallel.
    7598       23723 : TEST(ErrorReporting) {
    7599           5 :   CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
    7600             :   static const char* aDeps[] = {"B"};
    7601           5 :   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
    7602             :   static const char* bDeps[] = {"A"};
    7603           5 :   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
    7604           5 :   last_location = nullptr;
    7605             :   v8::ExtensionConfiguration config(1, bDeps);
    7606           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
    7607           5 :   CHECK(context.IsEmpty());
    7608           5 :   CHECK(last_location);
    7609           5 : }
    7610             : 
    7611             : static size_t dcheck_count;
    7612           0 : void DcheckErrorCallback(const char* file, int line, const char* message) {
    7613           0 :   last_message = message;
    7614           0 :   ++dcheck_count;
    7615           0 : }
    7616             : 
    7617       23723 : TEST(DcheckErrorHandler) {
    7618           5 :   V8::SetDcheckErrorHandler(DcheckErrorCallback);
    7619             : 
    7620           5 :   last_message = nullptr;
    7621           5 :   dcheck_count = 0;
    7622             : 
    7623             :   DCHECK(false && "w00t");
    7624             : #ifdef DEBUG
    7625             :   CHECK_EQ(dcheck_count, 1);
    7626             :   CHECK(last_message);
    7627             :   CHECK(std::string(last_message).find("w00t") != std::string::npos);
    7628             : #else
    7629             :   // The DCHECK should be a noop in non-DEBUG builds.
    7630           5 :   CHECK_EQ(dcheck_count, 0);
    7631             : #endif
    7632           5 : }
    7633             : 
    7634           6 : static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
    7635             :                                              v8::Local<Value> data) {
    7636           6 :   v8::Isolate* isolate = CcTest::isolate();
    7637           6 :   Local<Context> context = isolate->GetCurrentContext();
    7638          12 :   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
    7639          18 :   CHECK(v8::Undefined(isolate)
    7640             :             ->Equals(context, message->GetScriptOrigin().ResourceName())
    7641             :             .FromJust());
    7642          12 :   message->GetLineNumber(context).FromJust();
    7643           6 :   message->GetSourceLine(context).ToLocalChecked();
    7644           6 : }
    7645             : 
    7646             : 
    7647       23724 : THREADED_TEST(ErrorWithMissingScriptInfo) {
    7648           6 :   LocalContext context;
    7649          12 :   v8::HandleScope scope(context->GetIsolate());
    7650           6 :   context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
    7651             :   CompileRun("throw Error()");
    7652             :   context->GetIsolate()->RemoveMessageListeners(
    7653          12 :       MissingScriptInfoMessageListener);
    7654           6 : }
    7655             : 
    7656             : 
    7657             : struct FlagAndPersistent {
    7658             :   bool flag;
    7659             :   v8::Global<v8::Object> handle;
    7660             : };
    7661             : 
    7662             : 
    7663          80 : static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7664          40 :   data.GetParameter()->flag = true;
    7665             :   data.GetParameter()->handle.Reset();
    7666          40 : }
    7667             : 
    7668             : 
    7669          20 : static void IndependentWeakHandle(bool global_gc, bool interlinked) {
    7670          20 :   i::FLAG_stress_incremental_marking = false;
    7671             :   // Parallel scavenge introduces too much fragmentation.
    7672          20 :   i::FLAG_parallel_scavenge = false;
    7673          20 :   v8::Isolate* iso = CcTest::isolate();
    7674          20 :   v8::HandleScope scope(iso);
    7675          20 :   v8::Local<Context> context = Context::New(iso);
    7676             :   Context::Scope context_scope(context);
    7677             : 
    7678             :   FlagAndPersistent object_a, object_b;
    7679             : 
    7680             :   size_t big_heap_size = 0;
    7681             :   size_t big_array_size = 0;
    7682             : 
    7683             :   {
    7684          20 :     v8::HandleScope handle_scope(iso);
    7685          20 :     Local<Object> a(v8::Object::New(iso));
    7686          20 :     Local<Object> b(v8::Object::New(iso));
    7687             :     object_a.handle.Reset(iso, a);
    7688             :     object_b.handle.Reset(iso, b);
    7689          20 :     if (interlinked) {
    7690          30 :       a->Set(context, v8_str("x"), b).FromJust();
    7691          30 :       b->Set(context, v8_str("x"), a).FromJust();
    7692             :     }
    7693          20 :     if (global_gc) {
    7694          10 :       CcTest::CollectAllGarbage();
    7695             :     } else {
    7696          10 :       CcTest::CollectGarbage(i::NEW_SPACE);
    7697             :     }
    7698          20 :     v8::Local<Value> big_array = v8::Array::New(CcTest::isolate(), 5000);
    7699             :     // Verify that we created an array where the space was reserved up front.
    7700             :     big_array_size =
    7701             :         v8::internal::JSArray::cast(*v8::Utils::OpenHandle(*big_array))
    7702             :             ->elements()
    7703          20 :             ->Size();
    7704          20 :     CHECK_LE(20000, big_array_size);
    7705          60 :     a->Set(context, v8_str("y"), big_array).FromJust();
    7706          20 :     big_heap_size = CcTest::heap()->SizeOfObjects();
    7707             :   }
    7708             : 
    7709          20 :   object_a.flag = false;
    7710          20 :   object_b.flag = false;
    7711             :   object_a.handle.SetWeak(&object_a, &SetFlag,
    7712             :                           v8::WeakCallbackType::kParameter);
    7713             :   object_b.handle.SetWeak(&object_b, &SetFlag,
    7714             :                           v8::WeakCallbackType::kParameter);
    7715          20 :   CHECK(!object_b.handle.IsIndependent());
    7716             :   object_a.handle.MarkIndependent();
    7717             :   object_b.handle.MarkIndependent();
    7718          20 :   CHECK(object_b.handle.IsIndependent());
    7719          20 :   if (global_gc) {
    7720          10 :     CcTest::CollectAllGarbage();
    7721             :   } else {
    7722          10 :     CcTest::CollectGarbage(i::NEW_SPACE);
    7723             :   }
    7724             :   // A single GC should be enough to reclaim the memory, since we are using
    7725             :   // phantom handles.
    7726          20 :   CHECK_GT(big_heap_size - big_array_size, CcTest::heap()->SizeOfObjects());
    7727          20 :   CHECK(object_a.flag);
    7728          40 :   CHECK(object_b.flag);
    7729          20 : }
    7730             : 
    7731             : 
    7732       23723 : TEST(IndependentWeakHandle) {
    7733           5 :   IndependentWeakHandle(false, false);
    7734           5 :   IndependentWeakHandle(false, true);
    7735           5 :   IndependentWeakHandle(true, false);
    7736           5 :   IndependentWeakHandle(true, true);
    7737           5 : }
    7738             : 
    7739             : 
    7740             : class Trivial {
    7741             :  public:
    7742          12 :   explicit Trivial(int x) : x_(x) {}
    7743             : 
    7744          36 :   int x() { return x_; }
    7745          12 :   void set_x(int x) { x_ = x; }
    7746             : 
    7747             :  private:
    7748             :   int x_;
    7749             : };
    7750             : 
    7751             : 
    7752             : class Trivial2 {
    7753             :  public:
    7754          12 :   Trivial2(int x, int y) : y_(y), x_(x) {}
    7755             : 
    7756             :   int x() { return x_; }
    7757          12 :   void set_x(int x) { x_ = x; }
    7758             : 
    7759             :   int y() { return y_; }
    7760             :   void set_y(int y) { y_ = y; }
    7761             : 
    7762             :  private:
    7763             :   int y_;
    7764             :   int x_;
    7765             : };
    7766             : 
    7767          12 : void CheckInternalFields(
    7768          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
    7769             :   v8::Persistent<v8::Object>* handle = data.GetParameter();
    7770             :   handle->Reset();
    7771             :   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
    7772          12 :   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
    7773          12 :   CHECK_EQ(42, t1->x());
    7774          12 :   CHECK_EQ(103, t2->x());
    7775             :   t1->set_x(1729);
    7776             :   t2->set_x(33550336);
    7777          12 : }
    7778             : 
    7779          12 : void InternalFieldCallback(bool global_gc) {
    7780          12 :   LocalContext env;
    7781          12 :   v8::Isolate* isolate = env->GetIsolate();
    7782          24 :   v8::HandleScope scope(isolate);
    7783             : 
    7784          12 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    7785          12 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    7786             :   Trivial* t1;
    7787          24 :   Trivial2* t2;
    7788          12 :   instance_templ->SetInternalFieldCount(2);
    7789             :   v8::Persistent<v8::Object> handle;
    7790             :   {
    7791          12 :     v8::HandleScope scope(isolate);
    7792          12 :     Local<v8::Object> obj = templ->GetFunction(env.local())
    7793          12 :                                 .ToLocalChecked()
    7794          12 :                                 ->NewInstance(env.local())
    7795             :                                 .ToLocalChecked();
    7796             :     handle.Reset(isolate, obj);
    7797          12 :     CHECK_EQ(2, obj->InternalFieldCount());
    7798          12 :     CHECK(obj->GetInternalField(0)->IsUndefined());
    7799          12 :     t1 = new Trivial(42);
    7800          12 :     t2 = new Trivial2(103, 9);
    7801             : 
    7802          12 :     obj->SetAlignedPointerInInternalField(0, t1);
    7803             :     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
    7804          12 :     CHECK_EQ(42, t1->x());
    7805             : 
    7806          12 :     obj->SetAlignedPointerInInternalField(1, t2);
    7807             :     t2 =
    7808             :         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
    7809          12 :     CHECK_EQ(103, t2->x());
    7810             : 
    7811             :     handle.SetWeak<v8::Persistent<v8::Object>>(
    7812             :         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
    7813          12 :     if (!global_gc) {
    7814             :       handle.MarkIndependent();
    7815          12 :     }
    7816             :   }
    7817          12 :   if (global_gc) {
    7818           6 :     CcTest::CollectAllGarbage();
    7819             :   } else {
    7820           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    7821             :   }
    7822             : 
    7823          12 :   CHECK_EQ(1729, t1->x());
    7824          12 :   CHECK_EQ(33550336, t2->x());
    7825             : 
    7826          12 :   delete t1;
    7827          24 :   delete t2;
    7828          12 : }
    7829             : 
    7830       23724 : THREADED_TEST(InternalFieldCallback) {
    7831           6 :   InternalFieldCallback(false);
    7832           6 :   InternalFieldCallback(true);
    7833           6 : }
    7834             : 
    7835             : 
    7836          24 : static void ResetUseValueAndSetFlag(
    7837          48 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7838             :   // Blink will reset the handle, and then use the other handle, so they
    7839             :   // can't use the same backing slot.
    7840             :   data.GetParameter()->handle.Reset();
    7841          24 :   data.GetParameter()->flag = true;
    7842          24 : }
    7843             : 
    7844          12 : void v8::internal::heap::HeapTester::ResetWeakHandle(bool global_gc) {
    7845             :   using v8::Context;
    7846             :   using v8::Local;
    7847             :   using v8::Object;
    7848             : 
    7849          12 :   v8::Isolate* iso = CcTest::isolate();
    7850          12 :   v8::HandleScope scope(iso);
    7851          12 :   v8::Local<Context> context = Context::New(iso);
    7852             :   Context::Scope context_scope(context);
    7853             : 
    7854             :   FlagAndPersistent object_a, object_b;
    7855             : 
    7856             :   {
    7857          12 :     v8::HandleScope handle_scope(iso);
    7858          12 :     Local<Object> a(v8::Object::New(iso));
    7859          12 :     Local<Object> b(v8::Object::New(iso));
    7860             :     object_a.handle.Reset(iso, a);
    7861             :     object_b.handle.Reset(iso, b);
    7862          12 :     if (global_gc) {
    7863           6 :       CcTest::CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
    7864             :     } else {
    7865           6 :       CcTest::CollectGarbage(i::NEW_SPACE);
    7866          12 :     }
    7867             :   }
    7868             : 
    7869          12 :   object_a.flag = false;
    7870          12 :   object_b.flag = false;
    7871             :   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
    7872             :                           v8::WeakCallbackType::kParameter);
    7873             :   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
    7874             :                           v8::WeakCallbackType::kParameter);
    7875          12 :   if (!global_gc) {
    7876             :     object_a.handle.MarkIndependent();
    7877             :     object_b.handle.MarkIndependent();
    7878           6 :     CHECK(object_b.handle.IsIndependent());
    7879             :   }
    7880          12 :   if (global_gc) {
    7881           6 :     CcTest::CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
    7882             :   } else {
    7883           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    7884             :   }
    7885          12 :   CHECK(object_a.flag);
    7886          24 :   CHECK(object_b.flag);
    7887          12 : }
    7888             : 
    7889             : 
    7890       23724 : THREADED_HEAP_TEST(ResetWeakHandle) {
    7891           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(false);
    7892           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(true);
    7893           6 : }
    7894             : 
    7895          24 : static void InvokeScavenge() { CcTest::CollectGarbage(i::NEW_SPACE); }
    7896             : 
    7897          24 : static void InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
    7898             : 
    7899          12 : static void ForceScavenge2(
    7900          12 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7901          12 :   data.GetParameter()->flag = true;
    7902             :   InvokeScavenge();
    7903          12 : }
    7904             : 
    7905          12 : static void ForceScavenge1(
    7906          24 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7907             :   data.GetParameter()->handle.Reset();
    7908             :   data.SetSecondPassCallback(ForceScavenge2);
    7909          12 : }
    7910             : 
    7911             : 
    7912          12 : static void ForceMarkSweep2(
    7913          12 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7914          12 :   data.GetParameter()->flag = true;
    7915             :   InvokeMarkSweep();
    7916          12 : }
    7917             : 
    7918          12 : static void ForceMarkSweep1(
    7919          24 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7920             :   data.GetParameter()->handle.Reset();
    7921             :   data.SetSecondPassCallback(ForceMarkSweep2);
    7922          12 : }
    7923             : 
    7924             : 
    7925       23724 : THREADED_TEST(GCFromWeakCallbacks) {
    7926           6 :   v8::Isolate* isolate = CcTest::isolate();
    7927           6 :   v8::Locker locker(CcTest::isolate());
    7928          12 :   v8::HandleScope scope(isolate);
    7929           6 :   v8::Local<Context> context = Context::New(isolate);
    7930             :   Context::Scope context_scope(context);
    7931             : 
    7932             :   static const int kNumberOfGCTypes = 2;
    7933             :   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
    7934             :   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
    7935           6 :                                                     &ForceMarkSweep1};
    7936             : 
    7937             :   typedef void (*GCInvoker)();
    7938           6 :   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
    7939             : 
    7940          18 :   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
    7941          24 :     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
    7942             :       FlagAndPersistent object;
    7943             :       {
    7944          24 :         v8::HandleScope handle_scope(isolate);
    7945          48 :         object.handle.Reset(isolate, v8::Object::New(isolate));
    7946             :       }
    7947          24 :       object.flag = false;
    7948             :       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
    7949          24 :                             v8::WeakCallbackType::kParameter);
    7950             :       object.handle.MarkIndependent();
    7951          24 :       invoke_gc[outer_gc]();
    7952          24 :       EmptyMessageQueues(isolate);
    7953          24 :       CHECK(object.flag);
    7954             :     }
    7955           6 :   }
    7956           6 : }
    7957             : 
    7958             : 
    7959             : v8::Local<Function> args_fun;
    7960             : 
    7961             : 
    7962           6 : static void ArgumentsTestCallback(
    7963          18 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7964           6 :   ApiTestFuzzer::Fuzz();
    7965             :   v8::Isolate* isolate = args.GetIsolate();
    7966           6 :   Local<Context> context = isolate->GetCurrentContext();
    7967           6 :   CHECK_EQ(3, args.Length());
    7968          18 :   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
    7969          18 :   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
    7970          18 :   CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
    7971          12 :   CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
    7972           6 :   v8::HandleScope scope(args.GetIsolate());
    7973           6 :   CcTest::CollectAllGarbage();
    7974           6 : }
    7975             : 
    7976             : 
    7977       23724 : THREADED_TEST(Arguments) {
    7978           6 :   v8::Isolate* isolate = CcTest::isolate();
    7979           6 :   v8::HandleScope scope(isolate);
    7980           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    7981             :   global->Set(v8_str("f"),
    7982          18 :               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
    7983          12 :   LocalContext context(nullptr, global);
    7984             :   args_fun = context->Global()
    7985          24 :                  ->Get(context.local(), v8_str("f"))
    7986           6 :                  .ToLocalChecked()
    7987           6 :                  .As<Function>();
    7988          18 :   v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
    7989           6 : }
    7990             : 
    7991             : 
    7992             : static int p_getter_count;
    7993             : static int p_getter_count2;
    7994             : 
    7995             : 
    7996         240 : static void PGetter(Local<Name> name,
    7997             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    7998         240 :   ApiTestFuzzer::Fuzz();
    7999         240 :   p_getter_count++;
    8000         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8001         240 :   v8::Local<v8::Object> global = context->Global();
    8002         960 :   CHECK(
    8003             :       info.Holder()
    8004             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8005             :           .FromJust());
    8006         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8007         240 :     CHECK(info.This()
    8008             :               ->Equals(context,
    8009             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8010             :               .FromJust());
    8011         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8012         240 :     CHECK(info.This()
    8013             :               ->Equals(context,
    8014             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8015             :               .FromJust());
    8016         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8017         240 :     CHECK(info.This()
    8018             :               ->Equals(context,
    8019             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8020             :               .FromJust());
    8021         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8022         240 :     CHECK(info.This()
    8023             :               ->Equals(context,
    8024             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8025             :               .FromJust());
    8026             :   }
    8027         240 : }
    8028             : 
    8029             : 
    8030          12 : static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
    8031          12 :   ApiTestFuzzer::Fuzz();
    8032          12 :   LocalContext context;
    8033          84 :   CHECK(context->Global()
    8034             :             ->Set(context.local(), v8_str("o1"),
    8035             :                   obj->NewInstance(context.local()).ToLocalChecked())
    8036             :             .FromJust());
    8037             :   CompileRun(
    8038             :     "o1.__proto__ = { };"
    8039             :     "var o2 = { __proto__: o1 };"
    8040             :     "var o3 = { __proto__: o2 };"
    8041             :     "var o4 = { __proto__: o3 };"
    8042             :     "for (var i = 0; i < 10; i++) o4.p4;"
    8043             :     "for (var i = 0; i < 10; i++) o3.p3;"
    8044             :     "for (var i = 0; i < 10; i++) o2.p2;"
    8045          12 :     "for (var i = 0; i < 10; i++) o1.p1;");
    8046          12 : }
    8047             : 
    8048             : 
    8049         240 : static void PGetter2(Local<Name> name,
    8050             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    8051         240 :   ApiTestFuzzer::Fuzz();
    8052         240 :   p_getter_count2++;
    8053         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8054         240 :   v8::Local<v8::Object> global = context->Global();
    8055         960 :   CHECK(
    8056             :       info.Holder()
    8057             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8058             :           .FromJust());
    8059         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8060         240 :     CHECK(info.This()
    8061             :               ->Equals(context,
    8062             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8063             :               .FromJust());
    8064         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8065         240 :     CHECK(info.This()
    8066             :               ->Equals(context,
    8067             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8068             :               .FromJust());
    8069         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8070         240 :     CHECK(info.This()
    8071             :               ->Equals(context,
    8072             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8073             :               .FromJust());
    8074         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8075         240 :     CHECK(info.This()
    8076             :               ->Equals(context,
    8077             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8078             :               .FromJust());
    8079             :   }
    8080         240 : }
    8081             : 
    8082             : 
    8083       23724 : THREADED_TEST(GetterHolders) {
    8084           6 :   v8::Isolate* isolate = CcTest::isolate();
    8085           6 :   v8::HandleScope scope(isolate);
    8086           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8087          12 :   obj->SetAccessor(v8_str("p1"), PGetter);
    8088          12 :   obj->SetAccessor(v8_str("p2"), PGetter);
    8089          12 :   obj->SetAccessor(v8_str("p3"), PGetter);
    8090          12 :   obj->SetAccessor(v8_str("p4"), PGetter);
    8091           6 :   p_getter_count = 0;
    8092           6 :   RunHolderTest(obj);
    8093           6 :   CHECK_EQ(40, p_getter_count);
    8094           6 : }
    8095             : 
    8096             : 
    8097       23724 : THREADED_TEST(PreInterceptorHolders) {
    8098           6 :   v8::Isolate* isolate = CcTest::isolate();
    8099           6 :   v8::HandleScope scope(isolate);
    8100           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8101           6 :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
    8102           6 :   p_getter_count2 = 0;
    8103           6 :   RunHolderTest(obj);
    8104           6 :   CHECK_EQ(40, p_getter_count2);
    8105           6 : }
    8106             : 
    8107             : 
    8108       23724 : THREADED_TEST(ObjectInstantiation) {
    8109           6 :   v8::Isolate* isolate = CcTest::isolate();
    8110           6 :   v8::HandleScope scope(isolate);
    8111           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    8112          12 :   templ->SetAccessor(v8_str("t"), PGetter2);
    8113          12 :   LocalContext context;
    8114          36 :   CHECK(context->Global()
    8115             :             ->Set(context.local(), v8_str("o"),
    8116             :                   templ->NewInstance(context.local()).ToLocalChecked())
    8117             :             .FromJust());
    8118         600 :   for (int i = 0; i < 100; i++) {
    8119         600 :     v8::HandleScope inner_scope(CcTest::isolate());
    8120             :     v8::Local<v8::Object> obj =
    8121         600 :         templ->NewInstance(context.local()).ToLocalChecked();
    8122        3600 :     CHECK(!obj->Equals(context.local(), context->Global()
    8123             :                                             ->Get(context.local(), v8_str("o"))
    8124             :                                             .ToLocalChecked())
    8125             :                .FromJust());
    8126        3000 :     CHECK(
    8127             :         context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
    8128         600 :     v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
    8129        1800 :     CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
    8130        3000 :     CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
    8131         606 :   }
    8132           6 : }
    8133             : 
    8134             : 
    8135             : static int StrCmp16(uint16_t* a, uint16_t* b) {
    8136             :   while (true) {
    8137         168 :     if (*a == 0 && *b == 0) return 0;
    8138         138 :     if (*a != *b) return 0 + *a - *b;
    8139         132 :     a++;
    8140         132 :     b++;
    8141             :   }
    8142             : }
    8143             : 
    8144             : 
    8145             : static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
    8146             :   while (true) {
    8147         150 :     if (n-- == 0) return 0;
    8148         120 :     if (*a == 0 && *b == 0) return 0;
    8149         120 :     if (*a != *b) return 0 + *a - *b;
    8150         120 :     a++;
    8151         120 :     b++;
    8152             :   }
    8153             : }
    8154             : 
    8155             : 
    8156         552 : int GetUtf8Length(Local<String> str) {
    8157         552 :   int len = str->Utf8Length();
    8158         552 :   if (len < 0) {
    8159           0 :     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
    8160           0 :     i::String::Flatten(istr);
    8161           0 :     len = str->Utf8Length();
    8162             :   }
    8163         552 :   return len;
    8164             : }
    8165             : 
    8166             : 
    8167       23724 : THREADED_TEST(StringWrite) {
    8168           6 :   LocalContext context;
    8169          12 :   v8::HandleScope scope(context->GetIsolate());
    8170           6 :   v8::Local<String> str = v8_str("abcde");
    8171             :   // abc<Icelandic eth><Unicode snowman>.
    8172           6 :   v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
    8173             :   v8::Local<String> str3 =
    8174             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
    8175           6 :                               v8::NewStringType::kNormal, 7)
    8176           6 :           .ToLocalChecked();
    8177             :   // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
    8178           6 :   uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
    8179             :   v8::Local<String> orphans_str =
    8180             :       v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
    8181           6 :                                  v8::NewStringType::kNormal, 8)
    8182           6 :           .ToLocalChecked();
    8183             :   // single lead surrogate
    8184           6 :   uint16_t lead[1] = { 0xd800 };
    8185             :   v8::Local<String> lead_str =
    8186             :       v8::String::NewFromTwoByte(context->GetIsolate(), lead,
    8187           6 :                                  v8::NewStringType::kNormal, 1)
    8188           6 :           .ToLocalChecked();
    8189             :   // single trail surrogate
    8190           6 :   uint16_t trail[1] = { 0xdc00 };
    8191             :   v8::Local<String> trail_str =
    8192             :       v8::String::NewFromTwoByte(context->GetIsolate(), trail,
    8193           6 :                                  v8::NewStringType::kNormal, 1)
    8194           6 :           .ToLocalChecked();
    8195             :   // surrogate pair
    8196           6 :   uint16_t pair[2] = { 0xd800,  0xdc00 };
    8197             :   v8::Local<String> pair_str =
    8198             :       v8::String::NewFromTwoByte(context->GetIsolate(), pair,
    8199           6 :                                  v8::NewStringType::kNormal, 2)
    8200           6 :           .ToLocalChecked();
    8201             :   const int kStride = 4;  // Must match stride in for loops in JS below.
    8202             :   CompileRun(
    8203             :       "var left = '';"
    8204             :       "for (var i = 0; i < 0xd800; i += 4) {"
    8205             :       "  left = left + String.fromCharCode(i);"
    8206             :       "}");
    8207             :   CompileRun(
    8208             :       "var right = '';"
    8209             :       "for (var i = 0; i < 0xd800; i += 4) {"
    8210             :       "  right = String.fromCharCode(i) + right;"
    8211             :       "}");
    8212           6 :   v8::Local<v8::Object> global = context->Global();
    8213          18 :   Local<String> left_tree = global->Get(context.local(), v8_str("left"))
    8214           6 :                                 .ToLocalChecked()
    8215             :                                 .As<String>();
    8216          18 :   Local<String> right_tree = global->Get(context.local(), v8_str("right"))
    8217           6 :                                  .ToLocalChecked()
    8218             :                                  .As<String>();
    8219             : 
    8220           6 :   CHECK_EQ(5, str2->Length());
    8221           6 :   CHECK_EQ(0xd800 / kStride, left_tree->Length());
    8222           6 :   CHECK_EQ(0xd800 / kStride, right_tree->Length());
    8223             : 
    8224             :   char buf[100];
    8225             :   char utf8buf[0xd800 * 3];
    8226             :   uint16_t wbuf[100];
    8227             :   int len;
    8228             :   int charlen;
    8229             : 
    8230             :   memset(utf8buf, 0x1, 1000);
    8231           6 :   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
    8232           6 :   CHECK_EQ(9, len);
    8233           6 :   CHECK_EQ(5, charlen);
    8234           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
    8235             : 
    8236             :   memset(utf8buf, 0x1, 1000);
    8237           6 :   len = str2->WriteUtf8(utf8buf, 8, &charlen);
    8238           6 :   CHECK_EQ(8, len);
    8239           6 :   CHECK_EQ(5, charlen);
    8240           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
    8241             : 
    8242             :   memset(utf8buf, 0x1, 1000);
    8243           6 :   len = str2->WriteUtf8(utf8buf, 7, &charlen);
    8244           6 :   CHECK_EQ(5, len);
    8245           6 :   CHECK_EQ(4, charlen);
    8246           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
    8247             : 
    8248             :   memset(utf8buf, 0x1, 1000);
    8249           6 :   len = str2->WriteUtf8(utf8buf, 6, &charlen);
    8250           6 :   CHECK_EQ(5, len);
    8251           6 :   CHECK_EQ(4, charlen);
    8252           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
    8253             : 
    8254             :   memset(utf8buf, 0x1, 1000);
    8255           6 :   len = str2->WriteUtf8(utf8buf, 5, &charlen);
    8256           6 :   CHECK_EQ(5, len);
    8257           6 :   CHECK_EQ(4, charlen);
    8258           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
    8259             : 
    8260             :   memset(utf8buf, 0x1, 1000);
    8261           6 :   len = str2->WriteUtf8(utf8buf, 4, &charlen);
    8262           6 :   CHECK_EQ(3, len);
    8263           6 :   CHECK_EQ(3, charlen);
    8264           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
    8265             : 
    8266             :   memset(utf8buf, 0x1, 1000);
    8267           6 :   len = str2->WriteUtf8(utf8buf, 3, &charlen);
    8268           6 :   CHECK_EQ(3, len);
    8269           6 :   CHECK_EQ(3, charlen);
    8270           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
    8271             : 
    8272             :   memset(utf8buf, 0x1, 1000);
    8273           6 :   len = str2->WriteUtf8(utf8buf, 2, &charlen);
    8274           6 :   CHECK_EQ(2, len);
    8275           6 :   CHECK_EQ(2, charlen);
    8276           6 :   CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
    8277             : 
    8278             :   // allow orphan surrogates by default
    8279             :   memset(utf8buf, 0x1, 1000);
    8280           6 :   len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
    8281           6 :   CHECK_EQ(13, len);
    8282           6 :   CHECK_EQ(8, charlen);
    8283           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
    8284             : 
    8285             :   // replace orphan surrogates with unicode replacement character
    8286             :   memset(utf8buf, 0x1, 1000);
    8287             :   len = orphans_str->WriteUtf8(utf8buf,
    8288             :                                sizeof(utf8buf),
    8289             :                                &charlen,
    8290           6 :                                String::REPLACE_INVALID_UTF8);
    8291           6 :   CHECK_EQ(13, len);
    8292           6 :   CHECK_EQ(8, charlen);
    8293           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
    8294             : 
    8295             :   // replace single lead surrogate with unicode replacement character
    8296             :   memset(utf8buf, 0x1, 1000);
    8297             :   len = lead_str->WriteUtf8(utf8buf,
    8298             :                             sizeof(utf8buf),
    8299             :                             &charlen,
    8300           6 :                             String::REPLACE_INVALID_UTF8);
    8301           6 :   CHECK_EQ(4, len);
    8302           6 :   CHECK_EQ(1, charlen);
    8303           6 :   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
    8304             : 
    8305             :   // replace single trail surrogate with unicode replacement character
    8306             :   memset(utf8buf, 0x1, 1000);
    8307             :   len = trail_str->WriteUtf8(utf8buf,
    8308             :                              sizeof(utf8buf),
    8309             :                              &charlen,
    8310           6 :                              String::REPLACE_INVALID_UTF8);
    8311           6 :   CHECK_EQ(4, len);
    8312           6 :   CHECK_EQ(1, charlen);
    8313           6 :   CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
    8314             : 
    8315             :   // do not replace / write anything if surrogate pair does not fit the buffer
    8316             :   // space
    8317             :   memset(utf8buf, 0x1, 1000);
    8318             :   len = pair_str->WriteUtf8(utf8buf,
    8319             :                              3,
    8320             :                              &charlen,
    8321           6 :                              String::REPLACE_INVALID_UTF8);
    8322           6 :   CHECK_EQ(0, len);
    8323           6 :   CHECK_EQ(0, charlen);
    8324             : 
    8325             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8326           6 :   len = GetUtf8Length(left_tree);
    8327             :   int utf8_expected =
    8328             :       (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
    8329           6 :   CHECK_EQ(utf8_expected, len);
    8330           6 :   len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
    8331           6 :   CHECK_EQ(utf8_expected, len);
    8332           6 :   CHECK_EQ(0xd800 / kStride, charlen);
    8333          12 :   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
    8334          12 :   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
    8335          12 :   CHECK_EQ(0xc0 - kStride,
    8336             :            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
    8337           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8338             : 
    8339             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8340           6 :   len = GetUtf8Length(right_tree);
    8341           6 :   CHECK_EQ(utf8_expected, len);
    8342           6 :   len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
    8343           6 :   CHECK_EQ(utf8_expected, len);
    8344           6 :   CHECK_EQ(0xd800 / kStride, charlen);
    8345          12 :   CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
    8346          12 :   CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
    8347          12 :   CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
    8348           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8349             : 
    8350             :   memset(buf, 0x1, sizeof(buf));
    8351             :   memset(wbuf, 0x1, sizeof(wbuf));
    8352           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
    8353           6 :   CHECK_EQ(5, len);
    8354           6 :   len = str->Write(wbuf);
    8355           6 :   CHECK_EQ(5, len);
    8356           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8357           6 :   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8358           6 :   CHECK_EQ(0, StrCmp16(answer1, wbuf));
    8359             : 
    8360             :   memset(buf, 0x1, sizeof(buf));
    8361             :   memset(wbuf, 0x1, sizeof(wbuf));
    8362           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
    8363           6 :   CHECK_EQ(4, len);
    8364           6 :   len = str->Write(wbuf, 0, 4);
    8365           6 :   CHECK_EQ(4, len);
    8366           6 :   CHECK_EQ(0, strncmp("abcd\1", buf, 5));
    8367           6 :   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
    8368           6 :   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
    8369             : 
    8370             :   memset(buf, 0x1, sizeof(buf));
    8371             :   memset(wbuf, 0x1, sizeof(wbuf));
    8372           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
    8373           6 :   CHECK_EQ(5, len);
    8374           6 :   len = str->Write(wbuf, 0, 5);
    8375           6 :   CHECK_EQ(5, len);
    8376           6 :   CHECK_EQ(0, strncmp("abcde\1", buf, 6));
    8377           6 :   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
    8378           6 :   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
    8379             : 
    8380             :   memset(buf, 0x1, sizeof(buf));
    8381             :   memset(wbuf, 0x1, sizeof(wbuf));
    8382           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
    8383           6 :   CHECK_EQ(5, len);
    8384           6 :   len = str->Write(wbuf, 0, 6);
    8385           6 :   CHECK_EQ(5, len);
    8386           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8387           6 :   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8388           6 :   CHECK_EQ(0, StrCmp16(answer4, wbuf));
    8389             : 
    8390             :   memset(buf, 0x1, sizeof(buf));
    8391             :   memset(wbuf, 0x1, sizeof(wbuf));
    8392           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
    8393           6 :   CHECK_EQ(1, len);
    8394           6 :   len = str->Write(wbuf, 4, -1);
    8395           6 :   CHECK_EQ(1, len);
    8396           6 :   CHECK_EQ(0, strcmp("e", buf));
    8397           6 :   uint16_t answer5[] = {'e', '\0'};
    8398           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8399             : 
    8400             :   memset(buf, 0x1, sizeof(buf));
    8401             :   memset(wbuf, 0x1, sizeof(wbuf));
    8402           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
    8403           6 :   CHECK_EQ(1, len);
    8404           6 :   len = str->Write(wbuf, 4, 6);
    8405           6 :   CHECK_EQ(1, len);
    8406           6 :   CHECK_EQ(0, strcmp("e", buf));
    8407           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8408             : 
    8409             :   memset(buf, 0x1, sizeof(buf));
    8410             :   memset(wbuf, 0x1, sizeof(wbuf));
    8411           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
    8412           6 :   CHECK_EQ(1, len);
    8413           6 :   len = str->Write(wbuf, 4, 1);
    8414           6 :   CHECK_EQ(1, len);
    8415           6 :   CHECK_EQ(0, strncmp("e\1", buf, 2));
    8416           6 :   uint16_t answer6[] = {'e', 0x101};
    8417           6 :   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
    8418             : 
    8419             :   memset(buf, 0x1, sizeof(buf));
    8420             :   memset(wbuf, 0x1, sizeof(wbuf));
    8421           6 :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
    8422           6 :   CHECK_EQ(1, len);
    8423           6 :   len = str->Write(wbuf, 3, 1);
    8424           6 :   CHECK_EQ(1, len);
    8425           6 :   CHECK_EQ(0, strncmp("d\1", buf, 2));
    8426           6 :   uint16_t answer7[] = {'d', 0x101};
    8427           6 :   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
    8428             : 
    8429             :   memset(wbuf, 0x1, sizeof(wbuf));
    8430           6 :   wbuf[5] = 'X';
    8431           6 :   len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
    8432           6 :   CHECK_EQ(5, len);
    8433          12 :   CHECK_EQ('X', wbuf[5]);
    8434           6 :   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
    8435           6 :   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8436           6 :   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
    8437           6 :   CHECK_NE(0, StrCmp16(answer8b, wbuf));
    8438           6 :   wbuf[5] = '\0';
    8439           6 :   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
    8440             : 
    8441             :   memset(buf, 0x1, sizeof(buf));
    8442           6 :   buf[5] = 'X';
    8443             :   len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
    8444             :                           0,
    8445             :                           6,
    8446           6 :                           String::NO_NULL_TERMINATION);
    8447           6 :   CHECK_EQ(5, len);
    8448           6 :   CHECK_EQ('X', buf[5]);
    8449           6 :   CHECK_EQ(0, strncmp("abcde", buf, 5));
    8450           6 :   CHECK_NE(0, strcmp("abcde", buf));
    8451           6 :   buf[5] = '\0';
    8452           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8453             : 
    8454             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8455           6 :   utf8buf[8] = 'X';
    8456             :   len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
    8457           6 :                         String::NO_NULL_TERMINATION);
    8458           6 :   CHECK_EQ(8, len);
    8459           6 :   CHECK_EQ('X', utf8buf[8]);
    8460           6 :   CHECK_EQ(5, charlen);
    8461           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
    8462           6 :   CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
    8463           6 :   utf8buf[8] = '\0';
    8464           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
    8465             : 
    8466             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8467           6 :   utf8buf[5] = 'X';
    8468             :   len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
    8469           6 :                         String::NO_NULL_TERMINATION);
    8470           6 :   CHECK_EQ(5, len);
    8471           6 :   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
    8472           6 :   CHECK_EQ(5, charlen);
    8473           6 :   utf8buf[5] = '\0';
    8474           6 :   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
    8475             : 
    8476             :   memset(buf, 0x1, sizeof(buf));
    8477           6 :   len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
    8478           6 :   CHECK_EQ(7, len);
    8479           6 :   CHECK_EQ(0, strcmp("abc", buf));
    8480           6 :   CHECK_EQ(0, buf[3]);
    8481           6 :   CHECK_EQ(0, strcmp("def", buf + 4));
    8482             : 
    8483           6 :   CHECK_EQ(0, str->WriteOneByte(nullptr, 0, 0, String::NO_NULL_TERMINATION));
    8484           6 :   CHECK_EQ(0, str->WriteUtf8(nullptr, 0, 0, String::NO_NULL_TERMINATION));
    8485          12 :   CHECK_EQ(0, str->Write(nullptr, 0, 0, String::NO_NULL_TERMINATION));
    8486           6 : }
    8487             : 
    8488             : 
    8489          12 : static void Utf16Helper(
    8490             :     LocalContext& context,  // NOLINT
    8491             :     const char* name,
    8492             :     const char* lengths_name,
    8493             :     int len) {
    8494             :   Local<v8::Array> a = Local<v8::Array>::Cast(
    8495          60 :       context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
    8496             :   Local<v8::Array> alens =
    8497             :       Local<v8::Array>::Cast(context->Global()
    8498          48 :                                  ->Get(context.local(), v8_str(lengths_name))
    8499          12 :                                  .ToLocalChecked());
    8500         552 :   for (int i = 0; i < len; i++) {
    8501             :     Local<v8::String> string =
    8502        1080 :         Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
    8503             :     Local<v8::Number> expected_len = Local<v8::Number>::Cast(
    8504         540 :         alens->Get(context.local(), i).ToLocalChecked());
    8505         540 :     int length = GetUtf8Length(string);
    8506         540 :     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
    8507             :   }
    8508          12 : }
    8509             : 
    8510           6 : void TestUtf8DecodingAgainstReference(
    8511             :     const char* cases[],
    8512         474 :     const std::vector<std::vector<uint16_t>>& unicode_expected) {
    8513         132 :   for (size_t test_ix = 0; test_ix < unicode_expected.size(); ++test_ix) {
    8514          60 :     v8::Local<String> str = v8_str(cases[test_ix]);
    8515         180 :     CHECK_EQ(unicode_expected[test_ix].size(), str->Length());
    8516             : 
    8517          60 :     std::unique_ptr<uint16_t[]> buffer(new uint16_t[str->Length()]);
    8518          60 :     str->Write(buffer.get(), 0, -1, String::NO_NULL_TERMINATION);
    8519             : 
    8520        1044 :     for (size_t i = 0; i < unicode_expected[test_ix].size(); ++i) {
    8521         576 :       CHECK_EQ(unicode_expected[test_ix][i], buffer[i]);
    8522             :     }
    8523             :   }
    8524           6 : }
    8525             : 
    8526       23724 : THREADED_TEST(OverlongSequencesAndSurrogates) {
    8527           6 :   LocalContext context;
    8528          12 :   v8::HandleScope scope(context->GetIsolate());
    8529             : 
    8530             :   const char* cases[] = {
    8531             :       // Overlong 2-byte sequence.
    8532             :       "X\xc0\xbfY\0",
    8533             :       // Another overlong 2-byte sequence.
    8534             :       "X\xc1\xbfY\0",
    8535             :       // Overlong 3-byte sequence.
    8536             :       "X\xe0\x9f\xbfY\0",
    8537             :       // Overlong 4-byte sequence.
    8538             :       "X\xf0\x89\xbf\xbfY\0",
    8539             :       // Invalid 3-byte sequence (reserved for surrogates).
    8540             :       "X\xed\xa0\x80Y\0",
    8541             :       // Invalid 4-bytes sequence (value out of range).
    8542             :       "X\xf4\x90\x80\x80Y\0",
    8543             : 
    8544             :       // Start of an overlong 3-byte sequence but not enough continuation bytes.
    8545             :       "X\xe0\x9fY\0",
    8546             :       // Start of an overlong 4-byte sequence but not enough continuation bytes.
    8547             :       "X\xf0\x89\xbfY\0",
    8548             :       // Start of an invalid 3-byte sequence (reserved for surrogates) but not
    8549             :       // enough continuation bytes.
    8550             :       "X\xed\xa0Y\0",
    8551             :       // Start of an invalid 4-bytes sequence (value out of range) but not
    8552             :       // enough continuation bytes.
    8553             :       "X\xf4\x90\x80Y\0",
    8554           6 :   };
    8555             :   const std::vector<std::vector<uint16_t>> unicode_expected = {
    8556             :       {0x58, 0xfffd, 0xfffd, 0x59},
    8557             :       {0x58, 0xfffd, 0xfffd, 0x59},
    8558             :       {0x58, 0xfffd, 0xfffd, 0xfffd, 0x59},
    8559             :       {0x58, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x59},
    8560             :       {0x58, 0xfffd, 0xfffd, 0xfffd, 0x59},
    8561             :       {0x58, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x59},
    8562             :       {0x58, 0xfffd, 0xfffd, 0x59},
    8563             :       {0x58, 0xfffd, 0xfffd, 0xfffd, 0x59},
    8564             :       {0x58, 0xfffd, 0xfffd, 0x59},
    8565             :       {0x58, 0xfffd, 0xfffd, 0xfffd, 0x59},
    8566          12 :   };
    8567          12 :   CHECK_EQ(unicode_expected.size(), arraysize(cases));
    8568          12 :   TestUtf8DecodingAgainstReference(cases, unicode_expected);
    8569           6 : }
    8570             : 
    8571       23724 : THREADED_TEST(Utf16) {
    8572           6 :   LocalContext context;
    8573          12 :   v8::HandleScope scope(context->GetIsolate());
    8574             :   CompileRun(
    8575             :       "var pad = '01234567890123456789';"
    8576             :       "var p = [];"
    8577             :       "var plens = [20, 3, 3];"
    8578             :       "p.push('01234567890123456789');"
    8579             :       "var lead = 0xd800;"
    8580             :       "var trail = 0xdc00;"
    8581             :       "p.push(String.fromCharCode(0xd800));"
    8582             :       "p.push(String.fromCharCode(0xdc00));"
    8583             :       "var a = [];"
    8584             :       "var b = [];"
    8585             :       "var c = [];"
    8586             :       "var alens = [];"
    8587             :       "for (var i = 0; i < 3; i++) {"
    8588             :       "  p[1] = String.fromCharCode(lead++);"
    8589             :       "  for (var j = 0; j < 3; j++) {"
    8590             :       "    p[2] = String.fromCharCode(trail++);"
    8591             :       "    a.push(p[i] + p[j]);"
    8592             :       "    b.push(p[i] + p[j]);"
    8593             :       "    c.push(p[i] + p[j]);"
    8594             :       "    alens.push(plens[i] + plens[j]);"
    8595             :       "  }"
    8596             :       "}"
    8597             :       "alens[5] -= 2;"  // Here the surrogate pairs match up.
    8598             :       "var a2 = [];"
    8599             :       "var b2 = [];"
    8600             :       "var c2 = [];"
    8601             :       "var a2lens = [];"
    8602             :       "for (var m = 0; m < 9; m++) {"
    8603             :       "  for (var n = 0; n < 9; n++) {"
    8604             :       "    a2.push(a[m] + a[n]);"
    8605             :       "    b2.push(b[m] + b[n]);"
    8606             :       "    var newc = 'x' + c[m] + c[n] + 'y';"
    8607             :       "    c2.push(newc.substring(1, newc.length - 1));"
    8608             :       "    var utf = alens[m] + alens[n];"  // And here.
    8609             :            // The 'n's that start with 0xdc.. are 6-8
    8610             :            // The 'm's that end with 0xd8.. are 1, 4 and 7
    8611             :       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
    8612             :       "    a2lens.push(utf);"
    8613             :       "  }"
    8614             :       "}");
    8615           6 :   Utf16Helper(context, "a", "alens", 9);
    8616          12 :   Utf16Helper(context, "a2", "a2lens", 81);
    8617           6 : }
    8618             : 
    8619             : 
    8620             : static bool SameSymbol(Local<String> s1, Local<String> s2) {
    8621             :   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
    8622             :   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
    8623             :   return *is1 == *is2;
    8624             : }
    8625             : 
    8626             : 
    8627       23724 : THREADED_TEST(Utf16Symbol) {
    8628           6 :   LocalContext context;
    8629          12 :   v8::HandleScope scope(context->GetIsolate());
    8630             : 
    8631             :   Local<String> symbol1 =
    8632             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8633           6 :                               v8::NewStringType::kInternalized)
    8634           6 :           .ToLocalChecked();
    8635             :   Local<String> symbol2 =
    8636             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8637           6 :                               v8::NewStringType::kInternalized)
    8638           6 :           .ToLocalChecked();
    8639           6 :   CHECK(SameSymbol(symbol1, symbol2));
    8640             : 
    8641             :   CompileRun(
    8642             :       "var sym0 = 'benedictus';"
    8643             :       "var sym0b = 'S\303\270ren';"
    8644             :       "var sym1 = '\355\240\201\355\260\207';"
    8645             :       "var sym2 = '\360\220\220\210';"
    8646             :       "var sym3 = 'x\355\240\201\355\260\207';"
    8647             :       "var sym4 = 'x\360\220\220\210';"
    8648             :       "if (sym1.length != 2) throw sym1;"
    8649             :       "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
    8650             :       "if (sym2.length != 2) throw sym2;"
    8651             :       "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
    8652             :       "if (sym3.length != 3) throw sym3;"
    8653             :       "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
    8654             :       "if (sym4.length != 3) throw sym4;"
    8655             :       "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
    8656             :   Local<String> sym0 =
    8657             :       v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
    8658           6 :                               v8::NewStringType::kInternalized)
    8659           6 :           .ToLocalChecked();
    8660             :   Local<String> sym0b =
    8661             :       v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
    8662           6 :                               v8::NewStringType::kInternalized)
    8663           6 :           .ToLocalChecked();
    8664             :   Local<String> sym1 =
    8665             :       v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
    8666           6 :                               v8::NewStringType::kInternalized)
    8667           6 :           .ToLocalChecked();
    8668             :   Local<String> sym2 =
    8669             :       v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
    8670           6 :                               v8::NewStringType::kInternalized)
    8671           6 :           .ToLocalChecked();
    8672             :   Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
    8673             :                                                "x\355\240\201\355\260\207",
    8674           6 :                                                v8::NewStringType::kInternalized)
    8675           6 :                            .ToLocalChecked();
    8676             :   Local<String> sym4 =
    8677             :       v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
    8678           6 :                               v8::NewStringType::kInternalized)
    8679           6 :           .ToLocalChecked();
    8680           6 :   v8::Local<v8::Object> global = context->Global();
    8681             :   Local<Value> s0 =
    8682          18 :       global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
    8683             :   Local<Value> s0b =
    8684          18 :       global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
    8685             :   Local<Value> s1 =
    8686          18 :       global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
    8687             :   Local<Value> s2 =
    8688          18 :       global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
    8689             :   Local<Value> s3 =
    8690          18 :       global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
    8691             :   Local<Value> s4 =
    8692          18 :       global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
    8693           6 :   CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
    8694           6 :   CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
    8695           6 :   CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
    8696           6 :   CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
    8697           6 :   CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
    8698          12 :   CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
    8699           6 : }
    8700             : 
    8701             : 
    8702       23724 : THREADED_TEST(Utf16MissingTrailing) {
    8703           6 :   LocalContext context;
    8704          12 :   v8::HandleScope scope(context->GetIsolate());
    8705             : 
    8706             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8707             :   int size = 1024 * 64;
    8708           6 :   uint8_t* buffer = new uint8_t[size];
    8709       98310 :   for (int i = 0; i < size; i += 4) {
    8710       98304 :     buffer[i] = 0xf0;
    8711       98304 :     buffer[i + 1] = 0x9d;
    8712       98304 :     buffer[i + 2] = 0x80;
    8713       98304 :     buffer[i + 3] = 0x9e;
    8714             :   }
    8715             : 
    8716             :   // Now invoke the decoder without last 3 bytes
    8717             :   v8::Local<v8::String> str =
    8718             :       v8::String::NewFromUtf8(
    8719             :           context->GetIsolate(), reinterpret_cast<char*>(buffer),
    8720           6 :           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
    8721             :   USE(str);
    8722          12 :   delete[] buffer;
    8723           6 : }
    8724             : 
    8725             : 
    8726       23724 : THREADED_TEST(Utf16Trailing3Byte) {
    8727           6 :   LocalContext context;
    8728           6 :   v8::Isolate* isolate = context->GetIsolate();
    8729          12 :   v8::HandleScope scope(isolate);
    8730             : 
    8731             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8732             :   int size = 1024 * 63;
    8733           6 :   uint8_t* buffer = new uint8_t[size];
    8734      129030 :   for (int i = 0; i < size; i += 3) {
    8735      129024 :     buffer[i] = 0xe2;
    8736      129024 :     buffer[i + 1] = 0x80;
    8737      129024 :     buffer[i + 2] = 0xa6;
    8738             :   }
    8739             : 
    8740             :   // Now invoke the decoder without last 3 bytes
    8741             :   v8::Local<v8::String> str =
    8742             :       v8::String::NewFromUtf8(isolate, reinterpret_cast<char*>(buffer),
    8743             :                               v8::NewStringType::kNormal, size)
    8744           6 :           .ToLocalChecked();
    8745             : 
    8746          12 :   v8::String::Value value(isolate, str);
    8747           6 :   CHECK_EQ(value.length(), size / 3);
    8748          12 :   CHECK_EQ((*value)[value.length() - 1], 0x2026);
    8749             : 
    8750          12 :   delete[] buffer;
    8751           6 : }
    8752             : 
    8753             : 
    8754       23724 : THREADED_TEST(ToArrayIndex) {
    8755           6 :   LocalContext context;
    8756           6 :   v8::Isolate* isolate = context->GetIsolate();
    8757          12 :   v8::HandleScope scope(isolate);
    8758             : 
    8759           6 :   v8::Local<String> str = v8_str("42");
    8760           6 :   v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
    8761           6 :   CHECK(!index.IsEmpty());
    8762          18 :   CHECK_EQ(42.0,
    8763             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    8764           6 :   str = v8_str("42asdf");
    8765           6 :   index = str->ToArrayIndex(context.local());
    8766           6 :   CHECK(index.IsEmpty());
    8767           6 :   str = v8_str("-42");
    8768           6 :   index = str->ToArrayIndex(context.local());
    8769           6 :   CHECK(index.IsEmpty());
    8770           6 :   str = v8_str("4294967294");
    8771           6 :   index = str->ToArrayIndex(context.local());
    8772           6 :   CHECK(!index.IsEmpty());
    8773          18 :   CHECK_EQ(4294967294.0,
    8774             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    8775           6 :   v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
    8776           6 :   index = num->ToArrayIndex(context.local());
    8777           6 :   CHECK(!index.IsEmpty());
    8778          18 :   CHECK_EQ(1.0,
    8779             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    8780           6 :   num = v8::Number::New(isolate, -1);
    8781           6 :   index = num->ToArrayIndex(context.local());
    8782           6 :   CHECK(index.IsEmpty());
    8783           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    8784          12 :   index = obj->ToArrayIndex(context.local());
    8785          12 :   CHECK(index.IsEmpty());
    8786           6 : }
    8787             : 
    8788             : 
    8789       23724 : THREADED_TEST(ErrorConstruction) {
    8790           6 :   LocalContext context;
    8791          12 :   v8::HandleScope scope(context->GetIsolate());
    8792             : 
    8793           6 :   v8::Local<String> foo = v8_str("foo");
    8794           6 :   v8::Local<String> message = v8_str("message");
    8795           6 :   v8::Local<Value> range_error = v8::Exception::RangeError(foo);
    8796           6 :   CHECK(range_error->IsObject());
    8797          24 :   CHECK(range_error.As<v8::Object>()
    8798             :             ->Get(context.local(), message)
    8799             :             .ToLocalChecked()
    8800             :             ->Equals(context.local(), foo)
    8801             :             .FromJust());
    8802           6 :   v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
    8803           6 :   CHECK(reference_error->IsObject());
    8804          24 :   CHECK(reference_error.As<v8::Object>()
    8805             :             ->Get(context.local(), message)
    8806             :             .ToLocalChecked()
    8807             :             ->Equals(context.local(), foo)
    8808             :             .FromJust());
    8809           6 :   v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
    8810           6 :   CHECK(syntax_error->IsObject());
    8811          24 :   CHECK(syntax_error.As<v8::Object>()
    8812             :             ->Get(context.local(), message)
    8813             :             .ToLocalChecked()
    8814             :             ->Equals(context.local(), foo)
    8815             :             .FromJust());
    8816           6 :   v8::Local<Value> type_error = v8::Exception::TypeError(foo);
    8817           6 :   CHECK(type_error->IsObject());
    8818          24 :   CHECK(type_error.As<v8::Object>()
    8819             :             ->Get(context.local(), message)
    8820             :             .ToLocalChecked()
    8821             :             ->Equals(context.local(), foo)
    8822             :             .FromJust());
    8823           6 :   v8::Local<Value> error = v8::Exception::Error(foo);
    8824           6 :   CHECK(error->IsObject());
    8825          24 :   CHECK(error.As<v8::Object>()
    8826             :             ->Get(context.local(), message)
    8827             :             .ToLocalChecked()
    8828             :             ->Equals(context.local(), foo)
    8829           6 :             .FromJust());
    8830           6 : }
    8831             : 
    8832             : 
    8833          48 : static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
    8834          12 :   ApiTestFuzzer::Fuzz();
    8835          12 :   v8::Local<String> foo = v8_str("foo");
    8836          12 :   v8::Local<String> message = v8_str("message");
    8837          12 :   v8::Local<Value> error = v8::Exception::Error(foo);
    8838          12 :   CHECK(error->IsObject());
    8839          12 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8840          36 :   CHECK(error.As<v8::Object>()
    8841             :             ->Get(context, message)
    8842             :             .ToLocalChecked()
    8843             :             ->Equals(context, foo)
    8844             :             .FromJust());
    8845          12 :   info.GetIsolate()->ThrowException(error);
    8846             :   info.GetReturnValue().SetUndefined();
    8847          12 : }
    8848             : 
    8849             : 
    8850       23724 : THREADED_TEST(ExceptionCreateMessage) {
    8851           6 :   LocalContext context;
    8852          12 :   v8::HandleScope scope(context->GetIsolate());
    8853           6 :   v8::Local<String> foo_str = v8_str("foo");
    8854           6 :   v8::Local<String> message_str = v8_str("message");
    8855             : 
    8856           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
    8857             : 
    8858             :   Local<v8::FunctionTemplate> fun =
    8859           6 :       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
    8860           6 :   v8::Local<v8::Object> global = context->Global();
    8861          36 :   CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
    8862             :                     fun->GetFunction(context.local()).ToLocalChecked())
    8863             :             .FromJust());
    8864             : 
    8865          12 :   TryCatch try_catch(context->GetIsolate());
    8866             :   CompileRun(
    8867             :       "function f1() {\n"
    8868             :       "  throwV8Exception();\n"
    8869             :       "};\n"
    8870             :       "f1();");
    8871           6 :   CHECK(try_catch.HasCaught());
    8872             : 
    8873           6 :   v8::Local<v8::Value> error = try_catch.Exception();
    8874           6 :   CHECK(error->IsObject());
    8875          24 :   CHECK(error.As<v8::Object>()
    8876             :             ->Get(context.local(), message_str)
    8877             :             .ToLocalChecked()
    8878             :             ->Equals(context.local(), foo_str)
    8879             :             .FromJust());
    8880             : 
    8881             :   v8::Local<v8::Message> message =
    8882           6 :       v8::Exception::CreateMessage(context->GetIsolate(), error);
    8883           6 :   CHECK(!message.IsEmpty());
    8884          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    8885          12 :   CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
    8886             : 
    8887           6 :   v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
    8888           6 :   CHECK(!stackTrace.IsEmpty());
    8889           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    8890             : 
    8891           6 :   stackTrace = v8::Exception::GetStackTrace(error);
    8892           6 :   CHECK(!stackTrace.IsEmpty());
    8893           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    8894             : 
    8895           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
    8896             : 
    8897             :   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
    8898             :   // is false.
    8899           6 :   try_catch.Reset();
    8900             : 
    8901             :   CompileRun(
    8902             :       "function f2() {\n"
    8903             :       "  return throwV8Exception();\n"
    8904             :       "};\n"
    8905             :       "f2();");
    8906           6 :   CHECK(try_catch.HasCaught());
    8907             : 
    8908           6 :   error = try_catch.Exception();
    8909           6 :   CHECK(error->IsObject());
    8910          24 :   CHECK(error.As<v8::Object>()
    8911             :             ->Get(context.local(), message_str)
    8912             :             .ToLocalChecked()
    8913             :             ->Equals(context.local(), foo_str)
    8914             :             .FromJust());
    8915             : 
    8916           6 :   message = v8::Exception::CreateMessage(context->GetIsolate(), error);
    8917           6 :   CHECK(!message.IsEmpty());
    8918          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    8919          12 :   CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
    8920             : 
    8921             :   // Should be empty stack trace.
    8922           6 :   stackTrace = message->GetStackTrace();
    8923           6 :   CHECK(stackTrace.IsEmpty());
    8924          18 :   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
    8925           6 : }
    8926             : 
    8927             : 
    8928       23724 : THREADED_TEST(ExceptionCreateMessageLength) {
    8929           6 :   LocalContext context;
    8930          12 :   v8::HandleScope scope(context->GetIsolate());
    8931             : 
    8932             :   // Test that the message is not truncated.
    8933          12 :   TryCatch try_catch(context->GetIsolate());
    8934             :   CompileRun(
    8935             :       "var message = 'm';"
    8936             :       "while (message.length < 1000) message += message;"
    8937             :       "throw message;");
    8938           6 :   CHECK(try_catch.HasCaught());
    8939             : 
    8940          24 :   CHECK_LT(1000, try_catch.Message()->Get()->Length());
    8941           6 : }
    8942             : 
    8943             : 
    8944           0 : static void YGetter(Local<String> name,
    8945             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    8946           0 :   ApiTestFuzzer::Fuzz();
    8947           0 :   info.GetReturnValue().Set(v8_num(10));
    8948           0 : }
    8949             : 
    8950             : 
    8951           6 : static void YSetter(Local<String> name,
    8952             :                     Local<Value> value,
    8953             :                     const v8::PropertyCallbackInfo<void>& info) {
    8954             :   Local<Object> this_obj = Local<Object>::Cast(info.This());
    8955           6 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8956          12 :   if (this_obj->Has(context, name).FromJust())
    8957          12 :     this_obj->Delete(context, name).FromJust();
    8958          12 :   CHECK(this_obj->Set(context, name, value).FromJust());
    8959           6 : }
    8960             : 
    8961             : 
    8962       23724 : THREADED_TEST(DeleteAccessor) {
    8963           6 :   v8::Isolate* isolate = CcTest::isolate();
    8964           6 :   v8::HandleScope scope(isolate);
    8965           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8966           6 :   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
    8967          12 :   LocalContext context;
    8968             :   v8::Local<v8::Object> holder =
    8969           6 :       obj->NewInstance(context.local()).ToLocalChecked();
    8970          30 :   CHECK(context->Global()
    8971             :             ->Set(context.local(), v8_str("holder"), holder)
    8972             :             .FromJust());
    8973             :   v8::Local<Value> result =
    8974             :       CompileRun("holder.y = 11; holder.y = 12; holder.y");
    8975          18 :   CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
    8976           6 : }
    8977             : 
    8978             : 
    8979             : static int trouble_nesting = 0;
    8980          45 : static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    8981          15 :   ApiTestFuzzer::Fuzz();
    8982          15 :   trouble_nesting++;
    8983             : 
    8984             :   // Call a JS function that throws an uncaught exception.
    8985          15 :   Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    8986          15 :   Local<v8::Object> arg_this = context->Global();
    8987             :   Local<Value> trouble_callee =
    8988          15 :       (trouble_nesting == 3)
    8989          30 :           ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
    8990          60 :           : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
    8991          15 :   CHECK(trouble_callee->IsFunction());
    8992             :   args.GetReturnValue().Set(Function::Cast(*trouble_callee)
    8993          15 :                                 ->Call(context, arg_this, 0, nullptr)
    8994          30 :                                 .FromMaybe(v8::Local<v8::Value>()));
    8995          15 : }
    8996             : 
    8997             : 
    8998             : static int report_count = 0;
    8999           5 : static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
    9000             :                                              v8::Local<Value>) {
    9001           5 :   report_count++;
    9002           5 : }
    9003             : 
    9004             : 
    9005             : // Counts uncaught exceptions, but other tests running in parallel
    9006             : // also have uncaught exceptions.
    9007       23723 : TEST(ApiUncaughtException) {
    9008           5 :   report_count = 0;
    9009           5 :   LocalContext env;
    9010           5 :   v8::Isolate* isolate = env->GetIsolate();
    9011          10 :   v8::HandleScope scope(isolate);
    9012           5 :   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
    9013             : 
    9014             :   Local<v8::FunctionTemplate> fun =
    9015           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9016           5 :   v8::Local<v8::Object> global = env->Global();
    9017          25 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9018             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9019             :             .FromJust());
    9020             : 
    9021             :   CompileRun(
    9022             :       "function trouble_callee() {"
    9023             :       "  var x = null;"
    9024             :       "  return x.foo;"
    9025             :       "};"
    9026             :       "function trouble_caller() {"
    9027             :       "  trouble();"
    9028             :       "};");
    9029             :   Local<Value> trouble =
    9030          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9031           5 :   CHECK(trouble->IsFunction());
    9032             :   Local<Value> trouble_callee =
    9033          15 :       global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
    9034           5 :   CHECK(trouble_callee->IsFunction());
    9035             :   Local<Value> trouble_caller =
    9036          15 :       global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
    9037           5 :   CHECK(trouble_caller->IsFunction());
    9038             :   Function::Cast(*trouble_caller)
    9039          10 :       ->Call(env.local(), global, 0, nullptr)
    9040           5 :       .FromMaybe(v8::Local<v8::Value>());
    9041           5 :   CHECK_EQ(1, report_count);
    9042          10 :   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
    9043           5 : }
    9044             : 
    9045             : 
    9046             : static const char* script_resource_name = "ExceptionInNativeScript.js";
    9047           5 : static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
    9048             :                                                 v8::Local<Value>) {
    9049           5 :   v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
    9050          10 :   CHECK(!name_val.IsEmpty() && name_val->IsString());
    9051             :   v8::String::Utf8Value name(v8::Isolate::GetCurrent(),
    9052           5 :                              message->GetScriptOrigin().ResourceName());
    9053           5 :   CHECK_EQ(0, strcmp(script_resource_name, *name));
    9054             :   v8::Local<v8::Context> context =
    9055           5 :       v8::Isolate::GetCurrent()->GetCurrentContext();
    9056          10 :   CHECK_EQ(3, message->GetLineNumber(context).FromJust());
    9057             :   v8::String::Utf8Value source_line(
    9058             :       v8::Isolate::GetCurrent(),
    9059          15 :       message->GetSourceLine(context).ToLocalChecked());
    9060          10 :   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
    9061           5 : }
    9062             : 
    9063             : 
    9064       23723 : TEST(ExceptionInNativeScript) {
    9065           5 :   LocalContext env;
    9066           5 :   v8::Isolate* isolate = env->GetIsolate();
    9067          10 :   v8::HandleScope scope(isolate);
    9068           5 :   isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
    9069             : 
    9070             :   Local<v8::FunctionTemplate> fun =
    9071           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9072           5 :   v8::Local<v8::Object> global = env->Global();
    9073          25 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9074             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9075             :             .FromJust());
    9076             : 
    9077             :   CompileRunWithOrigin(
    9078             :       "function trouble() {\n"
    9079             :       "  var o = {};\n"
    9080             :       "  new o.foo();\n"
    9081             :       "};",
    9082           5 :       script_resource_name);
    9083             :   Local<Value> trouble =
    9084          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9085           5 :   CHECK(trouble->IsFunction());
    9086          10 :   CHECK(Function::Cast(*trouble)
    9087             :             ->Call(env.local(), global, 0, nullptr)
    9088             :             .IsEmpty());
    9089          10 :   isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
    9090           5 : }
    9091             : 
    9092             : 
    9093       23723 : TEST(CompilationErrorUsingTryCatchHandler) {
    9094           5 :   LocalContext env;
    9095          10 :   v8::HandleScope scope(env->GetIsolate());
    9096          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9097             :   v8_compile("This doesn't &*&@#$&*^ compile.");
    9098          10 :   CHECK(*try_catch.Exception());
    9099          10 :   CHECK(try_catch.HasCaught());
    9100           5 : }
    9101             : 
    9102             : 
    9103       23723 : TEST(TryCatchFinallyUsingTryCatchHandler) {
    9104           5 :   LocalContext env;
    9105          10 :   v8::HandleScope scope(env->GetIsolate());
    9106          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9107             :   CompileRun("try { throw ''; } catch (e) {}");
    9108           5 :   CHECK(!try_catch.HasCaught());
    9109             :   CompileRun("try { throw ''; } finally {}");
    9110           5 :   CHECK(try_catch.HasCaught());
    9111           5 :   try_catch.Reset();
    9112             :   CompileRun(
    9113             :       "(function() {"
    9114             :       "try { throw ''; } finally { return; }"
    9115             :       "})()");
    9116           5 :   CHECK(!try_catch.HasCaught());
    9117             :   CompileRun(
    9118             :       "(function()"
    9119             :       "  { try { throw ''; } finally { throw 0; }"
    9120             :       "})()");
    9121          10 :   CHECK(try_catch.HasCaught());
    9122           5 : }
    9123             : 
    9124             : 
    9125          20 : void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9126          10 :   v8::HandleScope scope(args.GetIsolate());
    9127             :   CompileRun(args[0]
    9128          10 :                  ->ToString(args.GetIsolate()->GetCurrentContext())
    9129          20 :                  .ToLocalChecked());
    9130          10 : }
    9131             : 
    9132             : 
    9133       23723 : TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
    9134           5 :   v8::Isolate* isolate = CcTest::isolate();
    9135           5 :   v8::HandleScope scope(isolate);
    9136           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    9137             :   templ->Set(v8_str("CEvaluate"),
    9138          15 :              v8::FunctionTemplate::New(isolate, CEvaluate));
    9139          10 :   LocalContext context(0, templ);
    9140          10 :   v8::TryCatch try_catch(isolate);
    9141             :   CompileRun("try {"
    9142             :              "  CEvaluate('throw 1;');"
    9143             :              "} finally {"
    9144             :              "}");
    9145           5 :   CHECK(try_catch.HasCaught());
    9146          10 :   CHECK(!try_catch.Message().IsEmpty());
    9147          10 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    9148           5 :   CHECK_EQ(0, strcmp(*exception_value, "1"));
    9149           5 :   try_catch.Reset();
    9150             :   CompileRun("try {"
    9151             :              "  CEvaluate('throw 1;');"
    9152             :              "} finally {"
    9153             :              "  throw 2;"
    9154             :              "}");
    9155           5 :   CHECK(try_catch.HasCaught());
    9156          10 :   CHECK(!try_catch.Message().IsEmpty());
    9157          10 :   String::Utf8Value finally_exception_value(isolate, try_catch.Exception());
    9158          10 :   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
    9159           5 : }
    9160             : 
    9161             : 
    9162             : // For use within the TestSecurityHandler() test.
    9163             : static bool g_security_callback_result = false;
    9164          35 : static bool SecurityTestCallback(Local<v8::Context> accessing_context,
    9165             :                                  Local<v8::Object> accessed_object,
    9166             :                                  Local<v8::Value> data) {
    9167             :   printf("a\n");
    9168          35 :   CHECK(!data.IsEmpty() && data->IsInt32());
    9169          70 :   CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
    9170          35 :   return g_security_callback_result;
    9171             : }
    9172             : 
    9173             : 
    9174             : // SecurityHandler can't be run twice
    9175       23723 : TEST(SecurityHandler) {
    9176           5 :   v8::Isolate* isolate = CcTest::isolate();
    9177           5 :   v8::HandleScope scope0(isolate);
    9178             :   v8::Local<v8::ObjectTemplate> global_template =
    9179           5 :       v8::ObjectTemplate::New(isolate);
    9180          10 :   global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
    9181             :   // Create an environment
    9182           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
    9183           5 :   context0->Enter();
    9184             : 
    9185           5 :   v8::Local<v8::Object> global0 = context0->Global();
    9186             :   v8::Local<Script> script0 = v8_compile("foo = 111");
    9187           5 :   script0->Run(context0).ToLocalChecked();
    9188          15 :   CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
    9189             :   v8::Local<Value> foo0 =
    9190          15 :       global0->Get(context0, v8_str("foo")).ToLocalChecked();
    9191          10 :   CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
    9192          15 :   v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
    9193          10 :   CHECK_EQ(999, z0->Int32Value(context0).FromJust());
    9194             : 
    9195             :   // Create another environment, should fail security checks.
    9196          10 :   v8::HandleScope scope1(isolate);
    9197             : 
    9198           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, global_template);
    9199           5 :   context1->Enter();
    9200             : 
    9201           5 :   v8::Local<v8::Object> global1 = context1->Global();
    9202          15 :   global1->Set(context1, v8_str("othercontext"), global0).FromJust();
    9203             :   // This set will fail the security check.
    9204             :   v8::Local<Script> script1 =
    9205             :       v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
    9206          10 :   CHECK(script1->Run(context1).IsEmpty());
    9207           5 :   g_security_callback_result = true;
    9208             :   // This read will pass the security check.
    9209             :   v8::Local<Value> foo1 =
    9210          15 :       global0->Get(context1, v8_str("foo")).ToLocalChecked();
    9211          10 :   CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
    9212             :   // This read will pass the security check.
    9213          15 :   v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
    9214          10 :   CHECK_EQ(999, z1->Int32Value(context1).FromJust());
    9215             : 
    9216             :   // Create another environment, should pass security checks.
    9217             :   {
    9218           5 :     v8::HandleScope scope2(isolate);
    9219          10 :     LocalContext context2;
    9220           5 :     v8::Local<v8::Object> global2 = context2->Global();
    9221          20 :     CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
    9222             :               .FromJust());
    9223             :     v8::Local<Script> script2 =
    9224             :         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
    9225           5 :     script2->Run(context2.local()).ToLocalChecked();
    9226             :     v8::Local<Value> foo2 =
    9227          15 :         global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
    9228          10 :     CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
    9229             :     v8::Local<Value> z2 =
    9230          15 :         global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
    9231          15 :     CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
    9232             :   }
    9233             : 
    9234           5 :   context1->Exit();
    9235          10 :   context0->Exit();
    9236           5 : }
    9237             : 
    9238             : 
    9239       23724 : THREADED_TEST(SecurityChecks) {
    9240           6 :   LocalContext env1;
    9241          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9242           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9243             : 
    9244           6 :   Local<Value> foo = v8_str("foo");
    9245           6 :   Local<Value> bar = v8_str("bar");
    9246             : 
    9247             :   // Set to the same domain.
    9248           6 :   env1->SetSecurityToken(foo);
    9249             : 
    9250             :   // Create a function in env1.
    9251             :   CompileRun("spy=function(){return spy;}");
    9252             :   Local<Value> spy =
    9253          30 :       env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
    9254           6 :   CHECK(spy->IsFunction());
    9255             : 
    9256             :   // Create another function accessing global objects.
    9257             :   CompileRun("spy2=function(){return new this.Array();}");
    9258             :   Local<Value> spy2 =
    9259          30 :       env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
    9260           6 :   CHECK(spy2->IsFunction());
    9261             : 
    9262             :   // Switch to env2 in the same domain and invoke spy on env2.
    9263             :   {
    9264           6 :     env2->SetSecurityToken(foo);
    9265             :     // Enter env2
    9266             :     Context::Scope scope_env2(env2);
    9267             :     Local<Value> result = Function::Cast(*spy)
    9268          12 :                               ->Call(env2, env2->Global(), 0, nullptr)
    9269           6 :                               .ToLocalChecked();
    9270           6 :     CHECK(result->IsFunction());
    9271             :   }
    9272             : 
    9273             :   {
    9274           6 :     env2->SetSecurityToken(bar);
    9275             :     Context::Scope scope_env2(env2);
    9276             : 
    9277             :     // Call cross_domain_call, it should throw an exception
    9278          12 :     v8::TryCatch try_catch(env1->GetIsolate());
    9279          18 :     CHECK(Function::Cast(*spy2)
    9280             :               ->Call(env2, env2->Global(), 0, nullptr)
    9281             :               .IsEmpty());
    9282           6 :     CHECK(try_catch.HasCaught());
    9283           6 :   }
    9284           6 : }
    9285             : 
    9286             : 
    9287             : // Regression test case for issue 1183439.
    9288       23724 : THREADED_TEST(SecurityChecksForPrototypeChain) {
    9289           6 :   LocalContext current;
    9290          12 :   v8::HandleScope scope(current->GetIsolate());
    9291           6 :   v8::Local<Context> other = Context::New(current->GetIsolate());
    9292             : 
    9293             :   // Change context to be able to get to the Object function in the
    9294             :   // other context without hitting the security checks.
    9295             :   v8::Local<Value> other_object;
    9296             :   { Context::Scope scope(other);
    9297             :     other_object =
    9298          24 :         other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
    9299          18 :     CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
    9300             :   }
    9301             : 
    9302          36 :   CHECK(current->Global()
    9303             :             ->Set(current.local(), v8_str("other"), other->Global())
    9304             :             .FromJust());
    9305          30 :   CHECK(v8_compile("other")
    9306             :             ->Run(current.local())
    9307             :             .ToLocalChecked()
    9308             :             ->Equals(current.local(), other->Global())
    9309             :             .FromJust());
    9310             : 
    9311             :   // Make sure the security check fails here and we get an undefined
    9312             :   // result instead of getting the Object function. Repeat in a loop
    9313             :   // to make sure to exercise the IC code.
    9314             :   v8::Local<Script> access_other0 = v8_compile("other.Object");
    9315             :   v8::Local<Script> access_other1 = v8_compile("other[42]");
    9316          36 :   for (int i = 0; i < 5; i++) {
    9317          60 :     CHECK(access_other0->Run(current.local()).IsEmpty());
    9318          60 :     CHECK(access_other1->Run(current.local()).IsEmpty());
    9319             :   }
    9320             : 
    9321             :   // Create an object that has 'other' in its prototype chain and make
    9322             :   // sure we cannot access the Object function indirectly through
    9323             :   // that. Repeat in a loop to make sure to exercise the IC code.
    9324             :   v8_compile(
    9325             :       "function F() { };"
    9326             :       "F.prototype = other;"
    9327             :       "var f = new F();")
    9328           6 :       ->Run(current.local())
    9329           6 :       .ToLocalChecked();
    9330             :   v8::Local<Script> access_f0 = v8_compile("f.Object");
    9331             :   v8::Local<Script> access_f1 = v8_compile("f[42]");
    9332          36 :   for (int j = 0; j < 5; j++) {
    9333          60 :     CHECK(access_f0->Run(current.local()).IsEmpty());
    9334          60 :     CHECK(access_f1->Run(current.local()).IsEmpty());
    9335             :   }
    9336             : 
    9337             :   // Now it gets hairy: Set the prototype for the other global object
    9338             :   // to be the current global object. The prototype chain for 'f' now
    9339             :   // goes through 'other' but ends up in the current global object.
    9340             :   { Context::Scope scope(other);
    9341          30 :     CHECK(other->Global()
    9342             :               ->Set(other, v8_str("__proto__"), current->Global())
    9343             :               .FromJust());
    9344             :   }
    9345             :   // Set a named and an index property on the current global
    9346             :   // object. To force the lookup to go through the other global object,
    9347             :   // the properties must not exist in the other global object.
    9348          30 :   CHECK(current->Global()
    9349             :             ->Set(current.local(), v8_str("foo"), v8_num(100))
    9350             :             .FromJust());
    9351          24 :   CHECK(current->Global()
    9352             :             ->Set(current.local(), v8_num(99), v8_num(101))
    9353             :             .FromJust());
    9354             :   // Try to read the properties from f and make sure that the access
    9355             :   // gets stopped by the security checks on the other global object.
    9356             :   Local<Script> access_f2 = v8_compile("f.foo");
    9357             :   Local<Script> access_f3 = v8_compile("f[99]");
    9358          36 :   for (int k = 0; k < 5; k++) {
    9359          60 :     CHECK(access_f2->Run(current.local()).IsEmpty());
    9360          60 :     CHECK(access_f3->Run(current.local()).IsEmpty());
    9361           6 :   }
    9362           6 : }
    9363             : 
    9364             : 
    9365             : static bool security_check_with_gc_called;
    9366             : 
    9367          10 : static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
    9368             :                                        Local<v8::Object> accessed_object,
    9369             :                                        Local<v8::Value> data) {
    9370          10 :   CcTest::CollectAllGarbage();
    9371          10 :   security_check_with_gc_called = true;
    9372          10 :   return true;
    9373             : }
    9374             : 
    9375             : 
    9376       23723 : TEST(SecurityTestGCAllowed) {
    9377           5 :   v8::Isolate* isolate = CcTest::isolate();
    9378           5 :   v8::HandleScope handle_scope(isolate);
    9379             :   v8::Local<v8::ObjectTemplate> object_template =
    9380           5 :       v8::ObjectTemplate::New(isolate);
    9381           5 :   object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
    9382             : 
    9383           5 :   v8::Local<Context> context = Context::New(isolate);
    9384             :   v8::Context::Scope context_scope(context);
    9385             : 
    9386          25 :   CHECK(context->Global()
    9387             :             ->Set(context, v8_str("obj"),
    9388             :                   object_template->NewInstance(context).ToLocalChecked())
    9389             :             .FromJust());
    9390             : 
    9391           5 :   security_check_with_gc_called = false;
    9392             :   CompileRun("obj[0] = new String(1002);");
    9393           5 :   CHECK(security_check_with_gc_called);
    9394             : 
    9395           5 :   security_check_with_gc_called = false;
    9396          20 :   CHECK(CompileRun("obj[0]")
    9397             :             ->ToString(context)
    9398             :             .ToLocalChecked()
    9399             :             ->Equals(context, v8_str("1002"))
    9400             :             .FromJust());
    9401          10 :   CHECK(security_check_with_gc_called);
    9402           5 : }
    9403             : 
    9404             : 
    9405       23724 : THREADED_TEST(CrossDomainDelete) {
    9406           6 :   LocalContext env1;
    9407          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9408           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9409             : 
    9410           6 :   Local<Value> foo = v8_str("foo");
    9411           6 :   Local<Value> bar = v8_str("bar");
    9412             : 
    9413             :   // Set to the same domain.
    9414           6 :   env1->SetSecurityToken(foo);
    9415           6 :   env2->SetSecurityToken(foo);
    9416             : 
    9417          30 :   CHECK(
    9418             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9419          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9420             : 
    9421             :   // Change env2 to a different domain and delete env1.prop.
    9422           6 :   env2->SetSecurityToken(bar);
    9423             :   {
    9424             :     Context::Scope scope_env2(env2);
    9425             :     Local<Value> result =
    9426             :         CompileRun("delete env1.prop");
    9427           6 :     CHECK(result.IsEmpty());
    9428             :   }
    9429             : 
    9430             :   // Check that env1.prop still exists.
    9431             :   Local<Value> v =
    9432          30 :       env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
    9433           6 :   CHECK(v->IsNumber());
    9434          18 :   CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
    9435           6 : }
    9436             : 
    9437             : 
    9438       23724 : THREADED_TEST(CrossDomainPropertyIsEnumerable) {
    9439           6 :   LocalContext env1;
    9440          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9441           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9442             : 
    9443           6 :   Local<Value> foo = v8_str("foo");
    9444           6 :   Local<Value> bar = v8_str("bar");
    9445             : 
    9446             :   // Set to the same domain.
    9447           6 :   env1->SetSecurityToken(foo);
    9448           6 :   env2->SetSecurityToken(foo);
    9449             : 
    9450          30 :   CHECK(
    9451             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9452          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9453             : 
    9454             :   // env1.prop is enumerable in env2.
    9455           6 :   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
    9456             :   {
    9457             :     Context::Scope scope_env2(env2);
    9458           6 :     Local<Value> result = CompileRun(test);
    9459           6 :     CHECK(result->IsTrue());
    9460             :   }
    9461             : 
    9462             :   // Change env2 to a different domain and test again.
    9463           6 :   env2->SetSecurityToken(bar);
    9464             :   {
    9465             :     Context::Scope scope_env2(env2);
    9466           6 :     Local<Value> result = CompileRun(test);
    9467           6 :     CHECK(result.IsEmpty());
    9468           6 :   }
    9469           6 : }
    9470             : 
    9471             : 
    9472       23724 : THREADED_TEST(CrossDomainFor) {
    9473           6 :   LocalContext env1;
    9474          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9475           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9476             : 
    9477           6 :   Local<Value> foo = v8_str("foo");
    9478           6 :   Local<Value> bar = v8_str("bar");
    9479             : 
    9480             :   // Set to the same domain.
    9481           6 :   env1->SetSecurityToken(foo);
    9482           6 :   env2->SetSecurityToken(foo);
    9483             : 
    9484          30 :   CHECK(
    9485             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9486          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9487             : 
    9488             :   // Change env2 to a different domain and set env1's global object
    9489             :   // as the __proto__ of an object in env2 and enumerate properties
    9490             :   // in for-in. It shouldn't enumerate properties on env1's global
    9491             :   // object. It shouldn't throw either, just silently ignore them.
    9492           6 :   env2->SetSecurityToken(bar);
    9493             :   {
    9494             :     Context::Scope scope_env2(env2);
    9495             :     Local<Value> result = CompileRun(
    9496             :         "(function() {"
    9497             :         "  try {"
    9498             :         "    for (var p in env1) {"
    9499             :         "      if (p == 'prop') return false;"
    9500             :         "    }"
    9501             :         "    return true;"
    9502             :         "  } catch (e) {"
    9503             :         "    return false;"
    9504             :         "  }"
    9505             :         "})()");
    9506           6 :     CHECK(result->IsTrue());
    9507           6 :   }
    9508           6 : }
    9509             : 
    9510             : 
    9511       23724 : THREADED_TEST(CrossDomainForInOnPrototype) {
    9512           6 :   LocalContext env1;
    9513          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9514           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9515             : 
    9516           6 :   Local<Value> foo = v8_str("foo");
    9517           6 :   Local<Value> bar = v8_str("bar");
    9518             : 
    9519             :   // Set to the same domain.
    9520           6 :   env1->SetSecurityToken(foo);
    9521           6 :   env2->SetSecurityToken(foo);
    9522             : 
    9523          30 :   CHECK(
    9524             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9525          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9526             : 
    9527             :   // Change env2 to a different domain and set env1's global object
    9528             :   // as the __proto__ of an object in env2 and enumerate properties
    9529             :   // in for-in. It shouldn't enumerate properties on env1's global
    9530             :   // object.
    9531           6 :   env2->SetSecurityToken(bar);
    9532             :   {
    9533             :     Context::Scope scope_env2(env2);
    9534             :     Local<Value> result = CompileRun(
    9535             :         "(function() {"
    9536             :         "  var obj = { '__proto__': env1 };"
    9537             :         "  try {"
    9538             :         "    for (var p in obj) {"
    9539             :         "      if (p == 'prop') return false;"
    9540             :         "    }"
    9541             :         "    return true;"
    9542             :         "  } catch (e) {"
    9543             :         "    return false;"
    9544             :         "  }"
    9545             :         "})()");
    9546           6 :     CHECK(result->IsTrue());
    9547           6 :   }
    9548           6 : }
    9549             : 
    9550             : 
    9551       23723 : TEST(ContextDetachGlobal) {
    9552           5 :   LocalContext env1;
    9553          10 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9554           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9555             : 
    9556             : 
    9557           5 :   Local<Value> foo = v8_str("foo");
    9558             : 
    9559             :   // Set to the same domain.
    9560           5 :   env1->SetSecurityToken(foo);
    9561           5 :   env2->SetSecurityToken(foo);
    9562             : 
    9563             :   // Enter env2
    9564           5 :   env2->Enter();
    9565             : 
    9566             :   // Create a function in env2 and add a reference to it in env1.
    9567           5 :   Local<v8::Object> global2 = env2->Global();
    9568          20 :   CHECK(global2->Set(env2, v8_str("prop"),
    9569             :                      v8::Integer::New(env2->GetIsolate(), 1))
    9570             :             .FromJust());
    9571             :   CompileRun("function getProp() {return prop;}");
    9572             : 
    9573          35 :   CHECK(env1->Global()
    9574             :             ->Set(env1.local(), v8_str("getProp"),
    9575             :                   global2->Get(env2, v8_str("getProp")).ToLocalChecked())
    9576             :             .FromJust());
    9577             : 
    9578             :   // Detach env2's global, and reuse the global object of env2
    9579           5 :   env2->Exit();
    9580           5 :   env2->DetachGlobal();
    9581             : 
    9582             :   v8::Local<Context> env3 = Context::New(
    9583           5 :       env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
    9584          10 :   env3->SetSecurityToken(v8_str("bar"));
    9585             : 
    9586           5 :   env3->Enter();
    9587           5 :   Local<v8::Object> global3 = env3->Global();
    9588          10 :   CHECK(global2->Equals(env3, global3).FromJust());
    9589          15 :   CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
    9590          15 :   CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
    9591          20 :   CHECK(global3->Set(env3, v8_str("prop"),
    9592             :                      v8::Integer::New(env3->GetIsolate(), -1))
    9593             :             .FromJust());
    9594          20 :   CHECK(global3->Set(env3, v8_str("prop2"),
    9595             :                      v8::Integer::New(env3->GetIsolate(), 2))
    9596             :             .FromJust());
    9597           5 :   env3->Exit();
    9598             : 
    9599             :   // Call getProp in env1, and it should return the value 1
    9600             :   {
    9601           5 :     Local<v8::Object> global1 = env1->Global();
    9602             :     Local<Value> get_prop =
    9603          20 :         global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
    9604           5 :     CHECK(get_prop->IsFunction());
    9605           5 :     v8::TryCatch try_catch(env1->GetIsolate());
    9606             :     Local<Value> r = Function::Cast(*get_prop)
    9607          10 :                          ->Call(env1.local(), global1, 0, nullptr)
    9608           5 :                          .ToLocalChecked();
    9609           5 :     CHECK(!try_catch.HasCaught());
    9610          10 :     CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
    9611             :   }
    9612             : 
    9613             :   // Check that env3 is not accessible from env1
    9614             :   {
    9615          10 :     v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
    9616           5 :     CHECK(r.IsEmpty());
    9617           5 :   }
    9618           5 : }
    9619             : 
    9620             : 
    9621       23723 : TEST(DetachGlobal) {
    9622           5 :   LocalContext env1;
    9623          10 :   v8::HandleScope scope(env1->GetIsolate());
    9624             : 
    9625             :   // Create second environment.
    9626           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9627             : 
    9628           5 :   Local<Value> foo = v8_str("foo");
    9629             : 
    9630             :   // Set same security token for env1 and env2.
    9631           5 :   env1->SetSecurityToken(foo);
    9632           5 :   env2->SetSecurityToken(foo);
    9633             : 
    9634             :   // Create a property on the global object in env2.
    9635             :   {
    9636             :     v8::Context::Scope scope(env2);
    9637          25 :     CHECK(env2->Global()
    9638             :               ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
    9639             :               .FromJust());
    9640             :   }
    9641             : 
    9642             :   // Create a reference to env2 global from env1 global.
    9643          30 :   CHECK(env1->Global()
    9644             :             ->Set(env1.local(), v8_str("other"), env2->Global())
    9645             :             .FromJust());
    9646             : 
    9647             :   // Check that we have access to other.p in env2 from env1.
    9648             :   Local<Value> result = CompileRun("other.p");
    9649           5 :   CHECK(result->IsInt32());
    9650          10 :   CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
    9651             : 
    9652             :   // Hold on to global from env2 and detach global from env2.
    9653           5 :   Local<v8::Object> global2 = env2->Global();
    9654           5 :   env2->DetachGlobal();
    9655             : 
    9656             :   // Check that the global has been detached. No other.p property can
    9657             :   // be found.
    9658             :   result = CompileRun("other.p");
    9659           5 :   CHECK(result.IsEmpty());
    9660             : 
    9661             :   // Reuse global2 for env3.
    9662             :   v8::Local<Context> env3 = Context::New(
    9663           5 :       env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
    9664          15 :   CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
    9665             : 
    9666             :   // Start by using the same security token for env3 as for env1 and env2.
    9667           5 :   env3->SetSecurityToken(foo);
    9668             : 
    9669             :   // Create a property on the global object in env3.
    9670             :   {
    9671             :     v8::Context::Scope scope(env3);
    9672          25 :     CHECK(env3->Global()
    9673             :               ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
    9674             :               .FromJust());
    9675             :   }
    9676             : 
    9677             :   // Check that other.p is now the property in env3 and that we have access.
    9678             :   result = CompileRun("other.p");
    9679           5 :   CHECK(result->IsInt32());
    9680          15 :   CHECK_EQ(24, result->Int32Value(env3).FromJust());
    9681           5 : }
    9682             : 
    9683             : 
    9684         130 : void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9685          65 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9686             :   info.GetReturnValue().Set(
    9687         260 :       context->Global()->Get(context, v8_str("x")).ToLocalChecked());
    9688          65 : }
    9689             : 
    9690             : 
    9691       23723 : TEST(DetachedAccesses) {
    9692           5 :   LocalContext env1;
    9693          10 :   v8::HandleScope scope(env1->GetIsolate());
    9694             : 
    9695             :   // Create second environment.
    9696             :   Local<ObjectTemplate> inner_global_template =
    9697          10 :       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
    9698             :   inner_global_template ->SetAccessorProperty(
    9699          10 :       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
    9700             :   v8::Local<Context> env2 =
    9701           5 :       Context::New(env1->GetIsolate(), nullptr, inner_global_template);
    9702             : 
    9703           5 :   Local<Value> foo = v8_str("foo");
    9704             : 
    9705             :   // Set same security token for env1 and env2.
    9706           5 :   env1->SetSecurityToken(foo);
    9707           5 :   env2->SetSecurityToken(foo);
    9708             : 
    9709          30 :   CHECK(env1->Global()
    9710             :             ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
    9711             :             .FromJust());
    9712             : 
    9713             :   {
    9714             :     v8::Context::Scope scope(env2);
    9715          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
    9716             :     CompileRun(
    9717             :         "function bound_x() { return x; }"
    9718             :         "function get_x()   { return this.x; }"
    9719             :         "function get_x_w() { return (function() {return this.x;})(); }");
    9720          25 :     CHECK(env1->Global()
    9721             :               ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
    9722             :               .FromJust());
    9723          25 :     CHECK(env1->Global()
    9724             :               ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
    9725             :               .FromJust());
    9726          25 :     CHECK(env1->Global()
    9727             :               ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
    9728             :               .FromJust());
    9729             :     env1->Global()
    9730             :         ->Set(env1.local(), v8_str("this_x"),
    9731          20 :               CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
    9732          10 :         .FromJust();
    9733             :   }
    9734             : 
    9735           5 :   Local<Object> env2_global = env2->Global();
    9736           5 :   env2->DetachGlobal();
    9737             : 
    9738             :   Local<Value> result;
    9739             :   result = CompileRun("bound_x()");
    9740          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
    9741             :   result = CompileRun("get_x()");
    9742           5 :   CHECK(result.IsEmpty());
    9743             :   result = CompileRun("get_x_w()");
    9744           5 :   CHECK(result.IsEmpty());
    9745             :   result = CompileRun("this_x()");
    9746          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
    9747             : 
    9748             :   // Reattach env2's proxy
    9749             :   env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
    9750           5 :                       env2_global);
    9751           5 :   env2->SetSecurityToken(foo);
    9752             :   {
    9753             :     v8::Context::Scope scope(env2);
    9754          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
    9755          25 :     CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9756             :     result = CompileRun(
    9757             :         "results = [];"
    9758             :         "for (var i = 0; i < 4; i++ ) {"
    9759             :         "  results.push(env1.bound_x());"
    9760             :         "  results.push(env1.get_x());"
    9761             :         "  results.push(env1.get_x_w());"
    9762             :         "  results.push(env1.this_x());"
    9763             :         "}"
    9764             :         "results");
    9765             :     Local<v8::Array> results = Local<v8::Array>::Cast(result);
    9766           5 :     CHECK_EQ(16u, results->Length());
    9767          20 :     for (int i = 0; i < 16; i += 4) {
    9768          80 :       CHECK(v8_str("env2_x")
    9769             :                 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
    9770             :                 .FromJust());
    9771          80 :       CHECK(v8_str("env1_x")
    9772             :                 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
    9773             :                 .FromJust());
    9774          80 :       CHECK(v8_str("env3_x")
    9775             :                 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
    9776             :                 .FromJust());
    9777          80 :       CHECK(v8_str("env2_x")
    9778             :                 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
    9779             :                 .FromJust());
    9780             :     }
    9781             :   }
    9782             : 
    9783             :   result = CompileRun(
    9784             :       "results = [];"
    9785             :       "for (var i = 0; i < 4; i++ ) {"
    9786             :       "  results.push(bound_x());"
    9787             :       "  results.push(get_x());"
    9788             :       "  results.push(get_x_w());"
    9789             :       "  results.push(this_x());"
    9790             :       "}"
    9791             :       "results");
    9792             :   Local<v8::Array> results = Local<v8::Array>::Cast(result);
    9793           5 :   CHECK_EQ(16u, results->Length());
    9794          20 :   for (int i = 0; i < 16; i += 4) {
    9795          80 :     CHECK(v8_str("env2_x")
    9796             :               ->Equals(env1.local(),
    9797             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
    9798             :               .FromJust());
    9799          80 :     CHECK(v8_str("env3_x")
    9800             :               ->Equals(env1.local(),
    9801             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
    9802             :               .FromJust());
    9803          80 :     CHECK(v8_str("env3_x")
    9804             :               ->Equals(env1.local(),
    9805             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
    9806             :               .FromJust());
    9807          80 :     CHECK(v8_str("env2_x")
    9808             :               ->Equals(env1.local(),
    9809             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
    9810             :               .FromJust());
    9811             :   }
    9812             : 
    9813             :   result = CompileRun(
    9814             :       "results = [];"
    9815             :       "for (var i = 0; i < 4; i++ ) {"
    9816             :       "  results.push(this.bound_x());"
    9817             :       "  results.push(this.get_x());"
    9818             :       "  results.push(this.get_x_w());"
    9819             :       "  results.push(this.this_x());"
    9820             :       "}"
    9821             :       "results");
    9822             :   results = Local<v8::Array>::Cast(result);
    9823           5 :   CHECK_EQ(16u, results->Length());
    9824          20 :   for (int i = 0; i < 16; i += 4) {
    9825          80 :     CHECK(v8_str("env2_x")
    9826             :               ->Equals(env1.local(),
    9827             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
    9828             :               .FromJust());
    9829          80 :     CHECK(v8_str("env1_x")
    9830             :               ->Equals(env1.local(),
    9831             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
    9832             :               .FromJust());
    9833          80 :     CHECK(v8_str("env3_x")
    9834             :               ->Equals(env1.local(),
    9835             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
    9836             :               .FromJust());
    9837          80 :     CHECK(v8_str("env2_x")
    9838             :               ->Equals(env1.local(),
    9839             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
    9840             :               .FromJust());
    9841           5 :   }
    9842           5 : }
    9843             : 
    9844             : 
    9845             : static bool allowed_access = false;
    9846         430 : static bool AccessBlocker(Local<v8::Context> accessing_context,
    9847             :                           Local<v8::Object> accessed_object,
    9848             :                           Local<v8::Value> data) {
    9849         430 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
    9850        1290 :   return context->Global()->Equals(context, accessed_object).FromJust() ||
    9851         430 :          allowed_access;
    9852             : }
    9853             : 
    9854             : 
    9855             : static int g_echo_value = -1;
    9856             : 
    9857             : 
    9858          15 : static void EchoGetter(
    9859             :     Local<String> name,
    9860             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    9861          15 :   info.GetReturnValue().Set(v8_num(g_echo_value));
    9862          15 : }
    9863             : 
    9864             : 
    9865          10 : static void EchoSetter(Local<String> name, Local<Value> value,
    9866             :                        const v8::PropertyCallbackInfo<void>& args) {
    9867          10 :   if (value->IsNumber())
    9868             :     g_echo_value =
    9869          20 :         value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
    9870          10 : }
    9871             : 
    9872             : 
    9873           0 : static void UnreachableGetter(
    9874             :     Local<String> name,
    9875             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    9876           0 :   CHECK(false);  // This function should not be called..
    9877             : }
    9878             : 
    9879             : 
    9880           0 : static void UnreachableSetter(Local<String>,
    9881             :                               Local<Value>,
    9882             :                               const v8::PropertyCallbackInfo<void>&) {
    9883           0 :   CHECK(false);  // This function should not be called.
    9884             : }
    9885             : 
    9886             : 
    9887           0 : static void UnreachableFunction(
    9888             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    9889           0 :   CHECK(false);  // This function should not be called..
    9890             : }
    9891             : 
    9892             : 
    9893       23723 : TEST(AccessControl) {
    9894           5 :   v8::Isolate* isolate = CcTest::isolate();
    9895           5 :   v8::HandleScope handle_scope(isolate);
    9896             :   v8::Local<v8::ObjectTemplate> global_template =
    9897           5 :       v8::ObjectTemplate::New(isolate);
    9898             : 
    9899           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
    9900             : 
    9901             :   // Add an accessor accessible by cross-domain JS code.
    9902             :   global_template->SetAccessor(
    9903             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
    9904           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
    9905             : 
    9906             : 
    9907             :   // Add an accessor that is not accessible by cross-domain JS code.
    9908             :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
    9909             :                                UnreachableSetter, v8::Local<Value>(),
    9910           5 :                                v8::DEFAULT);
    9911             : 
    9912             :   global_template->SetAccessorProperty(
    9913             :       v8_str("blocked_js_prop"),
    9914             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
    9915             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
    9916             :       v8::None,
    9917          15 :       v8::DEFAULT);
    9918             : 
    9919             :   // Create an environment
    9920           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
    9921           5 :   context0->Enter();
    9922             : 
    9923           5 :   v8::Local<v8::Object> global0 = context0->Global();
    9924             : 
    9925             :   // Define a property with JS getter and setter.
    9926             :   CompileRun(
    9927             :       "function getter() { return 'getter'; };\n"
    9928             :       "function setter() { return 'setter'; }\n"
    9929             :       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
    9930             : 
    9931             :   Local<Value> getter =
    9932          15 :       global0->Get(context0, v8_str("getter")).ToLocalChecked();
    9933             :   Local<Value> setter =
    9934          15 :       global0->Get(context0, v8_str("setter")).ToLocalChecked();
    9935             : 
    9936             :   // And define normal element.
    9937          15 :   CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
    9938             : 
    9939             :   // Define an element with JS getter and setter.
    9940             :   CompileRun(
    9941             :       "function el_getter() { return 'el_getter'; };\n"
    9942             :       "function el_setter() { return 'el_setter'; };\n"
    9943             :       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
    9944             : 
    9945             :   Local<Value> el_getter =
    9946          15 :       global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
    9947             :   Local<Value> el_setter =
    9948          15 :       global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
    9949             : 
    9950          10 :   v8::HandleScope scope1(isolate);
    9951             : 
    9952           5 :   v8::Local<Context> context1 = Context::New(isolate);
    9953           5 :   context1->Enter();
    9954             : 
    9955           5 :   v8::Local<v8::Object> global1 = context1->Global();
    9956          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
    9957             : 
    9958             :   // Access blocked property.
    9959             :   CompileRun("other.blocked_prop = 1");
    9960             : 
    9961           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
    9962           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
    9963             :             .IsEmpty());
    9964           5 :   CHECK(
    9965             :       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
    9966             : 
    9967             :   // Access blocked element.
    9968           5 :   CHECK(CompileRun("other[239] = 1").IsEmpty());
    9969             : 
    9970           5 :   CHECK(CompileRun("other[239]").IsEmpty());
    9971           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
    9972           5 :   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
    9973             : 
    9974           5 :   allowed_access = true;
    9975             :   // Now we can enumerate the property.
    9976             :   ExpectTrue("propertyIsEnumerable.call(other, '239')");
    9977           5 :   allowed_access = false;
    9978             : 
    9979             :   // Access a property with JS accessor.
    9980           5 :   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
    9981             : 
    9982           5 :   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
    9983           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
    9984             :             .IsEmpty());
    9985             : 
    9986           5 :   allowed_access = true;
    9987             : 
    9988           5 :   ExpectString("other.js_accessor_p", "getter");
    9989             :   ExpectObject(
    9990           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
    9991             :   ExpectObject(
    9992           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
    9993             :   ExpectUndefined(
    9994           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
    9995             : 
    9996           5 :   allowed_access = false;
    9997             : 
    9998             :   // Access an element with JS accessor.
    9999           5 :   CHECK(CompileRun("other[42] = 2").IsEmpty());
   10000             : 
   10001           5 :   CHECK(CompileRun("other[42]").IsEmpty());
   10002           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   10003             : 
   10004           5 :   allowed_access = true;
   10005             : 
   10006           5 :   ExpectString("other[42]", "el_getter");
   10007           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   10008           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   10009           5 :   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   10010             : 
   10011           5 :   allowed_access = false;
   10012             : 
   10013             :   v8::Local<Value> value;
   10014             : 
   10015             :   // Access accessible property
   10016             :   value = CompileRun("other.accessible_prop = 3");
   10017           5 :   CHECK(value->IsNumber());
   10018          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10019           5 :   CHECK_EQ(3, g_echo_value);
   10020             : 
   10021             :   value = CompileRun("other.accessible_prop");
   10022           5 :   CHECK(value->IsNumber());
   10023          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10024             : 
   10025             :   value = CompileRun(
   10026             :       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   10027           5 :   CHECK(value->IsNumber());
   10028          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10029             : 
   10030             :   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   10031           5 :   CHECK(value->IsTrue());
   10032             : 
   10033             :   // Enumeration doesn't enumerate accessors from inaccessible objects in
   10034             :   // the prototype chain even if the accessors are in themselves accessible.
   10035             :   // Enumeration doesn't throw, it silently ignores what it can't access.
   10036             :   value = CompileRun(
   10037             :       "(function() {"
   10038             :       "  var obj = { '__proto__': other };"
   10039             :       "  try {"
   10040             :       "    for (var p in obj) {"
   10041             :       "      if (p == 'accessible_prop' ||"
   10042             :       "          p == 'blocked_js_prop' ||"
   10043             :       "          p == 'blocked_js_prop') {"
   10044             :       "        return false;"
   10045             :       "      }"
   10046             :       "    }"
   10047             :       "    return true;"
   10048             :       "  } catch (e) {"
   10049             :       "    return false;"
   10050             :       "  }"
   10051             :       "})()");
   10052           5 :   CHECK(value->IsTrue());
   10053             : 
   10054             :   // Test that preventExtensions fails on a non-accessible object even if that
   10055             :   // object is already non-extensible.
   10056          20 :   CHECK(global1->Set(context1, v8_str("checked_object"),
   10057             :                      global_template->NewInstance(context1).ToLocalChecked())
   10058             :             .FromJust());
   10059           5 :   allowed_access = true;
   10060             :   CompileRun("Object.preventExtensions(checked_object)");
   10061             :   ExpectFalse("Object.isExtensible(checked_object)");
   10062           5 :   allowed_access = false;
   10063           5 :   CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
   10064             : 
   10065           5 :   context1->Exit();
   10066          10 :   context0->Exit();
   10067           5 : }
   10068             : 
   10069             : 
   10070       23723 : TEST(AccessControlES5) {
   10071           5 :   v8::Isolate* isolate = CcTest::isolate();
   10072           5 :   v8::HandleScope handle_scope(isolate);
   10073             :   v8::Local<v8::ObjectTemplate> global_template =
   10074           5 :       v8::ObjectTemplate::New(isolate);
   10075             : 
   10076           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10077             : 
   10078             :   // Add accessible accessor.
   10079             :   global_template->SetAccessor(
   10080             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10081           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10082             : 
   10083             : 
   10084             :   // Add an accessor that is not accessible by cross-domain JS code.
   10085             :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10086             :                                UnreachableSetter, v8::Local<Value>(),
   10087           5 :                                v8::DEFAULT);
   10088             : 
   10089             :   // Create an environment
   10090           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10091           5 :   context0->Enter();
   10092             : 
   10093           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10094             : 
   10095           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10096           5 :   context1->Enter();
   10097           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10098          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10099             : 
   10100             :   // Regression test for issue 1154.
   10101          10 :   CHECK(CompileRun("Object.keys(other).length == 1")
   10102             :             ->BooleanValue(context1)
   10103             :             .FromJust());
   10104          10 :   CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
   10105             :             ->BooleanValue(context1)
   10106             :             .FromJust());
   10107           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10108             : 
   10109             :   // Regression test for issue 1027.
   10110             :   CompileRun("Object.defineProperty(\n"
   10111             :              "  other, 'blocked_prop', {configurable: false})");
   10112           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10113           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10114             :             .IsEmpty());
   10115             : 
   10116             :   // Regression test for issue 1171.
   10117             :   ExpectTrue("Object.isExtensible(other)");
   10118             :   CompileRun("Object.preventExtensions(other)");
   10119             :   ExpectTrue("Object.isExtensible(other)");
   10120             : 
   10121             :   // Object.seal and Object.freeze.
   10122             :   CompileRun("Object.freeze(other)");
   10123             :   ExpectTrue("Object.isExtensible(other)");
   10124             : 
   10125             :   CompileRun("Object.seal(other)");
   10126             :   ExpectTrue("Object.isExtensible(other)");
   10127             : 
   10128             :   // Regression test for issue 1250.
   10129             :   // Make sure that we can set the accessible accessors value using normal
   10130             :   // assignment.
   10131             :   CompileRun("other.accessible_prop = 42");
   10132           5 :   CHECK_EQ(42, g_echo_value);
   10133             : 
   10134             :   // [[DefineOwnProperty]] always throws for access-checked objects.
   10135           5 :   CHECK(
   10136             :       CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
   10137             :           .IsEmpty());
   10138           5 :   CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
   10139           5 :   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
   10140           5 : }
   10141             : 
   10142         255 : static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
   10143             :                                 Local<v8::Object> global,
   10144             :                                 Local<v8::Value> data) {
   10145         255 :   i::PrintF("Access blocked.\n");
   10146         255 :   return false;
   10147             : }
   10148             : 
   10149           5 : static bool AccessAlwaysAllowed(Local<v8::Context> accessing_context,
   10150             :                                 Local<v8::Object> global,
   10151             :                                 Local<v8::Value> data) {
   10152           5 :   i::PrintF("Access allowed.\n");
   10153           5 :   return true;
   10154             : }
   10155             : 
   10156       23724 : THREADED_TEST(AccessControlGetOwnPropertyNames) {
   10157           6 :   v8::Isolate* isolate = CcTest::isolate();
   10158           6 :   v8::HandleScope handle_scope(isolate);
   10159           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10160             : 
   10161          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10162           6 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10163             : 
   10164             :   // Add an accessor accessible by cross-domain JS code.
   10165             :   obj_template->SetAccessor(
   10166             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10167           6 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10168             : 
   10169             :   // Create an environment
   10170           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   10171           6 :   context0->Enter();
   10172             : 
   10173           6 :   v8::Local<v8::Object> global0 = context0->Global();
   10174             : 
   10175          12 :   v8::HandleScope scope1(CcTest::isolate());
   10176             : 
   10177           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10178           6 :   context1->Enter();
   10179             : 
   10180           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10181          18 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10182          24 :   CHECK(global1->Set(context1, v8_str("object"),
   10183             :                      obj_template->NewInstance(context1).ToLocalChecked())
   10184             :             .FromJust());
   10185             : 
   10186             :   v8::Local<Value> value;
   10187             : 
   10188             :   // Attempt to get the property names of the other global object and
   10189             :   // of an object that requires access checks.  Accessing the other
   10190             :   // global object should be blocked by access checks on the global
   10191             :   // proxy object.  Accessing the object that requires access checks
   10192             :   // is blocked by the access checks on the object itself.
   10193             :   value = CompileRun(
   10194             :       "var names = Object.getOwnPropertyNames(other);"
   10195             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10196          12 :   CHECK(value->BooleanValue(context1).FromJust());
   10197             : 
   10198             :   value = CompileRun(
   10199             :       "var names = Object.getOwnPropertyNames(object);"
   10200             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10201          12 :   CHECK(value->BooleanValue(context1).FromJust());
   10202             : 
   10203           6 :   context1->Exit();
   10204          12 :   context0->Exit();
   10205           6 : }
   10206             : 
   10207             : 
   10208       23723 : TEST(Regress470113) {
   10209           5 :   v8::Isolate* isolate = CcTest::isolate();
   10210           5 :   v8::HandleScope handle_scope(isolate);
   10211           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10212           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10213          10 :   LocalContext env;
   10214          30 :   CHECK(env->Global()
   10215             :             ->Set(env.local(), v8_str("prohibited"),
   10216             :                   obj_template->NewInstance(env.local()).ToLocalChecked())
   10217             :             .FromJust());
   10218             : 
   10219             :   {
   10220           5 :     v8::TryCatch try_catch(isolate);
   10221             :     CompileRun(
   10222             :         "'use strict';\n"
   10223             :         "class C extends Object {\n"
   10224             :         "   m() { super.powned = 'Powned!'; }\n"
   10225             :         "}\n"
   10226             :         "let c = new C();\n"
   10227             :         "c.m.call(prohibited)");
   10228             : 
   10229           5 :     CHECK(try_catch.HasCaught());
   10230           5 :   }
   10231           5 : }
   10232             : 
   10233             : 
   10234           6 : static void ConstTenGetter(Local<String> name,
   10235             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   10236           6 :   info.GetReturnValue().Set(v8_num(10));
   10237           6 : }
   10238             : 
   10239             : 
   10240       23724 : THREADED_TEST(CrossDomainAccessors) {
   10241           6 :   v8::Isolate* isolate = CcTest::isolate();
   10242           6 :   v8::HandleScope handle_scope(isolate);
   10243             : 
   10244             :   v8::Local<v8::FunctionTemplate> func_template =
   10245           6 :       v8::FunctionTemplate::New(isolate);
   10246             : 
   10247             :   v8::Local<v8::ObjectTemplate> global_template =
   10248           6 :       func_template->InstanceTemplate();
   10249             : 
   10250             :   v8::Local<v8::ObjectTemplate> proto_template =
   10251           6 :       func_template->PrototypeTemplate();
   10252             : 
   10253             :   // Add an accessor to proto that's accessible by cross-domain JS code.
   10254             :   proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
   10255          12 :                               v8::Local<Value>(), v8::ALL_CAN_READ);
   10256             : 
   10257             :   // Add an accessor that is not accessible by cross-domain JS code.
   10258             :   global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
   10259          12 :                                v8::Local<Value>(), v8::DEFAULT);
   10260             : 
   10261           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10262           6 :   context0->Enter();
   10263             : 
   10264           6 :   Local<v8::Object> global = context0->Global();
   10265             :   // Add a normal property that shadows 'accessible'
   10266          18 :   CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
   10267             : 
   10268             :   // Enter a new context.
   10269          12 :   v8::HandleScope scope1(CcTest::isolate());
   10270           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10271           6 :   context1->Enter();
   10272             : 
   10273           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10274          18 :   CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
   10275             : 
   10276             :   // Should return 10, instead of 11
   10277             :   v8::Local<Value> value =
   10278           6 :       v8_compile("other.accessible")->Run(context1).ToLocalChecked();
   10279           6 :   CHECK(value->IsNumber());
   10280          12 :   CHECK_EQ(10, value->Int32Value(context1).FromJust());
   10281             : 
   10282             :   v8::MaybeLocal<v8::Value> maybe_value =
   10283           6 :       v8_compile("other.unreachable")->Run(context1);
   10284           6 :   CHECK(maybe_value.IsEmpty());
   10285             : 
   10286           6 :   context1->Exit();
   10287          12 :   context0->Exit();
   10288           6 : }
   10289             : 
   10290             : 
   10291             : static int access_count = 0;
   10292             : 
   10293         825 : static bool AccessCounter(Local<v8::Context> accessing_context,
   10294             :                           Local<v8::Object> accessed_object,
   10295             :                           Local<v8::Value> data) {
   10296         825 :   access_count++;
   10297         825 :   return true;
   10298             : }
   10299             : 
   10300             : 
   10301             : // This one is too easily disturbed by other tests.
   10302       23723 : TEST(AccessControlIC) {
   10303           5 :   access_count = 0;
   10304             : 
   10305           5 :   v8::Isolate* isolate = CcTest::isolate();
   10306           5 :   v8::HandleScope handle_scope(isolate);
   10307             : 
   10308             :   // Create an environment.
   10309           5 :   v8::Local<Context> context0 = Context::New(isolate);
   10310           5 :   context0->Enter();
   10311             : 
   10312             :   // Create an object that requires access-check functions to be
   10313             :   // called for cross-domain access.
   10314             :   v8::Local<v8::ObjectTemplate> object_template =
   10315           5 :       v8::ObjectTemplate::New(isolate);
   10316           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   10317             :   Local<v8::Object> object =
   10318           5 :       object_template->NewInstance(context0).ToLocalChecked();
   10319             : 
   10320          10 :   v8::HandleScope scope1(isolate);
   10321             : 
   10322             :   // Create another environment.
   10323           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10324           5 :   context1->Enter();
   10325             : 
   10326             :   // Make easy access to the object from the other environment.
   10327           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10328          15 :   CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
   10329             : 
   10330             :   v8::Local<Value> value;
   10331             : 
   10332             :   // Check that the named access-control function is called every time.
   10333             :   CompileRun("function testProp(obj) {"
   10334             :              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   10335             :              "  for (var j = 0; j < 10; j++) obj.prop;"
   10336             :              "  return obj.prop"
   10337             :              "}");
   10338             :   value = CompileRun("testProp(obj)");
   10339           5 :   CHECK(value->IsNumber());
   10340          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10341           5 :   CHECK_EQ(21, access_count);
   10342             : 
   10343             :   // Check that the named access-control function is called every time.
   10344             :   CompileRun("var p = 'prop';"
   10345             :              "function testKeyed(obj) {"
   10346             :              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   10347             :              "  for (var j = 0; j < 10; j++) obj[p];"
   10348             :              "  return obj[p];"
   10349             :              "}");
   10350             :   // Use obj which requires access checks.  No inline caching is used
   10351             :   // in that case.
   10352             :   value = CompileRun("testKeyed(obj)");
   10353           5 :   CHECK(value->IsNumber());
   10354          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10355           5 :   CHECK_EQ(42, access_count);
   10356             :   // Force the inline caches into generic state and try again.
   10357             :   CompileRun("testKeyed({ a: 0 })");
   10358             :   CompileRun("testKeyed({ b: 0 })");
   10359             :   value = CompileRun("testKeyed(obj)");
   10360           5 :   CHECK(value->IsNumber());
   10361          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10362           5 :   CHECK_EQ(63, access_count);
   10363             : 
   10364             :   // Check that the indexed access-control function is called every time.
   10365           5 :   access_count = 0;
   10366             : 
   10367             :   CompileRun("function testIndexed(obj) {"
   10368             :              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   10369             :              "  for (var j = 0; j < 10; j++) obj[0];"
   10370             :              "  return obj[0]"
   10371             :              "}");
   10372             :   value = CompileRun("testIndexed(obj)");
   10373           5 :   CHECK(value->IsNumber());
   10374          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10375           5 :   CHECK_EQ(21, access_count);
   10376             :   // Force the inline caches into generic state.
   10377             :   CompileRun("testIndexed(new Array(1))");
   10378             :   // Test that the indexed access check is called.
   10379             :   value = CompileRun("testIndexed(obj)");
   10380           5 :   CHECK(value->IsNumber());
   10381          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10382           5 :   CHECK_EQ(42, access_count);
   10383             : 
   10384           5 :   access_count = 0;
   10385             :   // Check that the named access check is called when invoking
   10386             :   // functions on an object that requires access checks.
   10387             :   CompileRun("obj.f = function() {}");
   10388             :   CompileRun("function testCallNormal(obj) {"
   10389             :              "  for (var i = 0; i < 10; i++) obj.f();"
   10390             :              "}");
   10391             :   CompileRun("testCallNormal(obj)");
   10392           5 :   printf("%i\n", access_count);
   10393           5 :   CHECK_EQ(11, access_count);
   10394             : 
   10395             :   // Force obj into slow case.
   10396             :   value = CompileRun("delete obj.prop");
   10397          10 :   CHECK(value->BooleanValue(context1).FromJust());
   10398             :   // Force inline caches into dictionary probing mode.
   10399             :   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   10400             :   // Test that the named access check is called.
   10401             :   value = CompileRun("testProp(obj);");
   10402           5 :   CHECK(value->IsNumber());
   10403          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10404           5 :   CHECK_EQ(33, access_count);
   10405             : 
   10406             :   // Force the call inline cache into dictionary probing mode.
   10407             :   CompileRun("o.f = function() {}; testCallNormal(o)");
   10408             :   // Test that the named access check is still called for each
   10409             :   // invocation of the function.
   10410             :   value = CompileRun("testCallNormal(obj)");
   10411           5 :   CHECK_EQ(43, access_count);
   10412             : 
   10413           5 :   context1->Exit();
   10414          10 :   context0->Exit();
   10415           5 : }
   10416             : 
   10417             : 
   10418       23724 : THREADED_TEST(Version) { v8::V8::GetVersion(); }
   10419             : 
   10420             : 
   10421          18 : static void InstanceFunctionCallback(
   10422          18 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10423          18 :   ApiTestFuzzer::Fuzz();
   10424          18 :   args.GetReturnValue().Set(v8_num(12));
   10425          18 : }
   10426             : 
   10427             : 
   10428       23724 : THREADED_TEST(InstanceProperties) {
   10429           6 :   LocalContext context;
   10430           6 :   v8::Isolate* isolate = context->GetIsolate();
   10431          12 :   v8::HandleScope handle_scope(isolate);
   10432             : 
   10433           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10434           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10435             : 
   10436          18 :   instance->Set(v8_str("x"), v8_num(42));
   10437             :   instance->Set(v8_str("f"),
   10438          18 :                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10439             : 
   10440           6 :   Local<Value> o = t->GetFunction(context.local())
   10441           6 :                        .ToLocalChecked()
   10442           6 :                        ->NewInstance(context.local())
   10443             :                        .ToLocalChecked();
   10444             : 
   10445          30 :   CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
   10446             :   Local<Value> value = CompileRun("i.x");
   10447          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10448             : 
   10449             :   value = CompileRun("i.f()");
   10450          18 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10451           6 : }
   10452             : 
   10453             : 
   10454         696 : static void GlobalObjectInstancePropertiesGet(
   10455             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   10456         696 :   ApiTestFuzzer::Fuzz();
   10457         696 : }
   10458             : 
   10459             : 
   10460       23724 : THREADED_TEST(GlobalObjectInstanceProperties) {
   10461           6 :   v8::Isolate* isolate = CcTest::isolate();
   10462           6 :   v8::HandleScope handle_scope(isolate);
   10463             : 
   10464             :   Local<Value> global_object;
   10465             : 
   10466           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10467             :   t->InstanceTemplate()->SetHandler(
   10468          12 :       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   10469           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10470          18 :   instance_template->Set(v8_str("x"), v8_num(42));
   10471             :   instance_template->Set(v8_str("f"),
   10472             :                          v8::FunctionTemplate::New(isolate,
   10473          18 :                                                    InstanceFunctionCallback));
   10474             : 
   10475             :   // The script to check how Crankshaft compiles missing global function
   10476             :   // invocations.  function g is not defined and should throw on call.
   10477             :   const char* script =
   10478             :       "function wrapper(call) {"
   10479             :       "  var x = 0, y = 1;"
   10480             :       "  for (var i = 0; i < 1000; i++) {"
   10481             :       "    x += i * 100;"
   10482             :       "    y += i * 100;"
   10483             :       "  }"
   10484             :       "  if (call) g();"
   10485             :       "}"
   10486             :       "for (var i = 0; i < 17; i++) wrapper(false);"
   10487             :       "var thrown = 0;"
   10488             :       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10489             :       "thrown";
   10490             : 
   10491             :   {
   10492           6 :     LocalContext env(nullptr, instance_template);
   10493             :     // Hold on to the global object so it can be used again in another
   10494             :     // environment initialization.
   10495           6 :     global_object = env->Global();
   10496             : 
   10497             :     Local<Value> value = CompileRun("x");
   10498          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10499             :     value = CompileRun("f()");
   10500          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10501             :     value = CompileRun(script);
   10502          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10503             :   }
   10504             : 
   10505             :   {
   10506             :     // Create new environment reusing the global object.
   10507           6 :     LocalContext env(nullptr, instance_template, global_object);
   10508             :     Local<Value> value = CompileRun("x");
   10509          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10510             :     value = CompileRun("f()");
   10511          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10512             :     value = CompileRun(script);
   10513          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10514           6 :   }
   10515           6 : }
   10516             : 
   10517       23724 : THREADED_TEST(ObjectGetOwnPropertyNames) {
   10518           6 :   LocalContext context;
   10519           6 :   v8::Isolate* isolate = context->GetIsolate();
   10520          12 :   v8::HandleScope handle_scope(isolate);
   10521             : 
   10522             :   v8::Local<v8::Object> value =
   10523           6 :       v8::Local<v8::Object>::Cast(v8::StringObject::New(v8_str("test")));
   10524             :   v8::Local<v8::Array> properties;
   10525             : 
   10526          12 :   CHECK(value
   10527             :             ->GetOwnPropertyNames(context.local(),
   10528             :                                   static_cast<v8::PropertyFilter>(
   10529             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10530             :                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10531             :             .ToLocal(&properties));
   10532           6 :   CHECK_EQ(5u, properties->Length());
   10533             :   v8::Local<v8::Value> property;
   10534          18 :   CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
   10535             :         property->IsString());
   10536          18 :   CHECK(property.As<v8::String>()
   10537             :             ->Equals(context.local(), v8_str("length"))
   10538             :             .FromMaybe(false));
   10539          24 :   for (int i = 0; i < 4; ++i) {
   10540             :     v8::Local<v8::Value> property;
   10541          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10542             :           property->IsInt32());
   10543          24 :     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10544             :   }
   10545             : 
   10546          12 :   CHECK(value->GetOwnPropertyNames(context.local(), v8::ONLY_ENUMERABLE)
   10547             :             .ToLocal(&properties));
   10548           6 :   CHECK_EQ(4u, properties->Length());
   10549          24 :   for (int i = 0; i < 4; ++i) {
   10550             :     v8::Local<v8::Value> property;
   10551          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10552             :           property->IsInt32());
   10553          24 :     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10554             :   }
   10555             : 
   10556           6 :   value = value->GetPrototype().As<v8::Object>();
   10557          12 :   CHECK(value
   10558             :             ->GetOwnPropertyNames(context.local(),
   10559             :                                   static_cast<v8::PropertyFilter>(
   10560             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10561             :                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10562             :             .ToLocal(&properties));
   10563             :   bool concat_found = false;
   10564             :   bool starts_with_found = false;
   10565         270 :   for (uint32_t i = 0; i < properties->Length(); ++i) {
   10566             :     v8::Local<v8::Value> property;
   10567         540 :     CHECK(properties->Get(context.local(), i).ToLocal(&property));
   10568         270 :     if (!property->IsString()) continue;
   10569         270 :     if (!concat_found)
   10570             :       concat_found = property.As<v8::String>()
   10571         180 :                          ->Equals(context.local(), v8_str("concat"))
   10572         120 :                          .FromMaybe(false);
   10573         270 :     if (!starts_with_found)
   10574             :       starts_with_found = property.As<v8::String>()
   10575         648 :                               ->Equals(context.local(), v8_str("startsWith"))
   10576         432 :                               .FromMaybe(false);
   10577             :   }
   10578          12 :   CHECK(concat_found && starts_with_found);
   10579           6 : }
   10580             : 
   10581       23724 : THREADED_TEST(CallKnownGlobalReceiver) {
   10582           6 :   v8::Isolate* isolate = CcTest::isolate();
   10583           6 :   v8::HandleScope handle_scope(isolate);
   10584             : 
   10585             :   Local<Value> global_object;
   10586             : 
   10587           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10588           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10589             : 
   10590             :   // The script to check that we leave global object not
   10591             :   // global object proxy on stack when we deoptimize from inside
   10592             :   // arguments evaluation.
   10593             :   // To provoke error we need to both force deoptimization
   10594             :   // from arguments evaluation and to force CallIC to take
   10595             :   // CallIC_Miss code path that can't cope with global proxy.
   10596             :   const char* script =
   10597             :       "function bar(x, y) { try { } finally { } }"
   10598             :       "function baz(x) { try { } finally { } }"
   10599             :       "function bom(x) { try { } finally { } }"
   10600             :       "function foo(x) { bar([x], bom(2)); }"
   10601             :       "for (var i = 0; i < 10000; i++) foo(1);"
   10602             :       "foo";
   10603             : 
   10604             :   Local<Value> foo;
   10605             :   {
   10606           6 :     LocalContext env(nullptr, instance_template);
   10607             :     // Hold on to the global object so it can be used again in another
   10608             :     // environment initialization.
   10609           6 :     global_object = env->Global();
   10610           6 :     foo = CompileRun(script);
   10611             :   }
   10612             : 
   10613             :   {
   10614             :     // Create new environment reusing the global object.
   10615           6 :     LocalContext env(nullptr, instance_template, global_object);
   10616          30 :     CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
   10617           6 :     CompileRun("foo()");
   10618           6 :   }
   10619           6 : }
   10620             : 
   10621             : 
   10622           6 : static void ShadowFunctionCallback(
   10623           6 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10624           6 :   ApiTestFuzzer::Fuzz();
   10625           6 :   args.GetReturnValue().Set(v8_num(42));
   10626           6 : }
   10627             : 
   10628             : 
   10629             : static int shadow_y;
   10630             : static int shadow_y_setter_call_count;
   10631             : static int shadow_y_getter_call_count;
   10632             : 
   10633             : 
   10634           6 : static void ShadowYSetter(Local<String>,
   10635             :                           Local<Value>,
   10636             :                           const v8::PropertyCallbackInfo<void>&) {
   10637           6 :   shadow_y_setter_call_count++;
   10638           6 :   shadow_y = 42;
   10639           6 : }
   10640             : 
   10641             : 
   10642           6 : static void ShadowYGetter(Local<String> name,
   10643             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10644           6 :   ApiTestFuzzer::Fuzz();
   10645           6 :   shadow_y_getter_call_count++;
   10646           6 :   info.GetReturnValue().Set(v8_num(shadow_y));
   10647           6 : }
   10648             : 
   10649             : 
   10650           0 : static void ShadowIndexedGet(uint32_t index,
   10651             :                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10652           0 : }
   10653             : 
   10654             : 
   10655          30 : static void ShadowNamedGet(Local<Name> key,
   10656          30 :                            const v8::PropertyCallbackInfo<v8::Value>&) {}
   10657             : 
   10658             : 
   10659       23724 : THREADED_TEST(ShadowObject) {
   10660           6 :   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10661           6 :   v8::Isolate* isolate = CcTest::isolate();
   10662           6 :   v8::HandleScope handle_scope(isolate);
   10663             : 
   10664           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10665          12 :   LocalContext context(nullptr, global_template);
   10666             : 
   10667           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10668             :   t->InstanceTemplate()->SetHandler(
   10669          12 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   10670             :   t->InstanceTemplate()->SetHandler(
   10671          12 :       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   10672           6 :   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10673           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10674             : 
   10675             :   proto->Set(v8_str("f"),
   10676             :              v8::FunctionTemplate::New(isolate,
   10677             :                                        ShadowFunctionCallback,
   10678          18 :                                        Local<Value>()));
   10679          18 :   proto->Set(v8_str("x"), v8_num(12));
   10680             : 
   10681          12 :   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   10682             : 
   10683           6 :   Local<Value> o = t->GetFunction(context.local())
   10684           6 :                        .ToLocalChecked()
   10685           6 :                        ->NewInstance(context.local())
   10686             :                        .ToLocalChecked();
   10687          30 :   CHECK(context->Global()
   10688             :             ->Set(context.local(), v8_str("__proto__"), o)
   10689             :             .FromJust());
   10690             : 
   10691             :   Local<Value> value =
   10692             :       CompileRun("this.propertyIsEnumerable(0)");
   10693           6 :   CHECK(value->IsBoolean());
   10694          12 :   CHECK(!value->BooleanValue(context.local()).FromJust());
   10695             : 
   10696             :   value = CompileRun("x");
   10697          12 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10698             : 
   10699             :   value = CompileRun("f()");
   10700          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10701             : 
   10702             :   CompileRun("y = 43");
   10703           6 :   CHECK_EQ(1, shadow_y_setter_call_count);
   10704             :   value = CompileRun("y");
   10705           6 :   CHECK_EQ(1, shadow_y_getter_call_count);
   10706          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10707           6 : }
   10708             : 
   10709             : 
   10710       23724 : THREADED_TEST(HiddenPrototype) {
   10711           6 :   LocalContext context;
   10712           6 :   v8::Isolate* isolate = context->GetIsolate();
   10713          12 :   v8::HandleScope handle_scope(isolate);
   10714             : 
   10715           6 :   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10716          24 :   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10717           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10718           6 :   t1->SetHiddenPrototype(true);
   10719          24 :   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10720           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10721           6 :   t2->SetHiddenPrototype(true);
   10722          24 :   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10723           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10724          24 :   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10725             : 
   10726           6 :   Local<v8::Object> o0 = t0->GetFunction(context.local())
   10727           6 :                              .ToLocalChecked()
   10728           6 :                              ->NewInstance(context.local())
   10729             :                              .ToLocalChecked();
   10730           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10731           6 :                              .ToLocalChecked()
   10732           6 :                              ->NewInstance(context.local())
   10733             :                              .ToLocalChecked();
   10734           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10735           6 :                              .ToLocalChecked()
   10736           6 :                              ->NewInstance(context.local())
   10737             :                              .ToLocalChecked();
   10738           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10739           6 :                              .ToLocalChecked()
   10740           6 :                              ->NewInstance(context.local())
   10741             :                              .ToLocalChecked();
   10742             : 
   10743             :   // Setting the prototype on an object skips hidden prototypes.
   10744          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10745             :                   .ToLocalChecked()
   10746             :                   ->Int32Value(context.local())
   10747             :                   .FromJust());
   10748          18 :   CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
   10749          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10750             :                   .ToLocalChecked()
   10751             :                   ->Int32Value(context.local())
   10752             :                   .FromJust());
   10753          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10754             :                   .ToLocalChecked()
   10755             :                   ->Int32Value(context.local())
   10756             :                   .FromJust());
   10757          18 :   CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
   10758          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10759             :                   .ToLocalChecked()
   10760             :                   ->Int32Value(context.local())
   10761             :                   .FromJust());
   10762          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10763             :                   .ToLocalChecked()
   10764             :                   ->Int32Value(context.local())
   10765             :                   .FromJust());
   10766          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10767             :                   .ToLocalChecked()
   10768             :                   ->Int32Value(context.local())
   10769             :                   .FromJust());
   10770          18 :   CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
   10771          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10772             :                   .ToLocalChecked()
   10773             :                   ->Int32Value(context.local())
   10774             :                   .FromJust());
   10775          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10776             :                   .ToLocalChecked()
   10777             :                   ->Int32Value(context.local())
   10778             :                   .FromJust());
   10779          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10780             :                   .ToLocalChecked()
   10781             :                   ->Int32Value(context.local())
   10782             :                   .FromJust());
   10783          24 :   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   10784             :                   .ToLocalChecked()
   10785             :                   ->Int32Value(context.local())
   10786             :                   .FromJust());
   10787             : 
   10788             :   // Getting the prototype of o0 should get the first visible one
   10789             :   // which is o3.  Therefore, z should not be defined on the prototype
   10790             :   // object.
   10791             :   Local<Value> proto =
   10792          18 :       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   10793           6 :   CHECK(proto->IsObject());
   10794          18 :   CHECK(proto.As<v8::Object>()
   10795             :             ->Get(context.local(), v8_str("z"))
   10796             :             .ToLocalChecked()
   10797           6 :             ->IsUndefined());
   10798           6 : }
   10799             : 
   10800             : 
   10801       23724 : THREADED_TEST(HiddenPrototypeSet) {
   10802           6 :   LocalContext context;
   10803           6 :   v8::Isolate* isolate = context->GetIsolate();
   10804          12 :   v8::HandleScope handle_scope(isolate);
   10805             : 
   10806           6 :   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
   10807           6 :   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
   10808           6 :   ht->SetHiddenPrototype(true);
   10809           6 :   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
   10810          24 :   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10811             : 
   10812           6 :   Local<v8::Object> o = ot->GetFunction(context.local())
   10813           6 :                             .ToLocalChecked()
   10814           6 :                             ->NewInstance(context.local())
   10815             :                             .ToLocalChecked();
   10816           6 :   Local<v8::Object> h = ht->GetFunction(context.local())
   10817           6 :                             .ToLocalChecked()
   10818           6 :                             ->NewInstance(context.local())
   10819             :                             .ToLocalChecked();
   10820           6 :   Local<v8::Object> p = pt->GetFunction(context.local())
   10821           6 :                             .ToLocalChecked()
   10822           6 :                             ->NewInstance(context.local())
   10823             :                             .ToLocalChecked();
   10824          18 :   CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
   10825          18 :   CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
   10826             : 
   10827             :   // Setting a property that exists on the hidden prototype goes there.
   10828          18 :   CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
   10829          24 :   CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
   10830             :                   .ToLocalChecked()
   10831             :                   ->Int32Value(context.local())
   10832             :                   .FromJust());
   10833          24 :   CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
   10834             :                   .ToLocalChecked()
   10835             :                   ->Int32Value(context.local())
   10836             :                   .FromJust());
   10837          18 :   CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
   10838             : 
   10839             :   // Setting a new property should not be forwarded to the hidden prototype.
   10840          18 :   CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
   10841          24 :   CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
   10842             :                   .ToLocalChecked()
   10843             :                   ->Int32Value(context.local())
   10844             :                   .FromJust());
   10845          18 :   CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   10846          18 :   CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   10847             : 
   10848             :   // Setting a property that only exists on a prototype of the hidden prototype
   10849             :   // is treated normally again.
   10850          18 :   CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
   10851          24 :   CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
   10852             :                   .ToLocalChecked()
   10853             :                   ->Int32Value(context.local())
   10854             :                   .FromJust());
   10855          24 :   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   10856             :                   .ToLocalChecked()
   10857             :                   ->Int32Value(context.local())
   10858             :                   .FromJust());
   10859          24 :   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   10860             :                   .ToLocalChecked()
   10861             :                   ->Int32Value(context.local())
   10862             :                   .FromJust());
   10863          18 :   CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
   10864          24 :   CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
   10865             :                   .ToLocalChecked()
   10866             :                   ->Int32Value(context.local())
   10867             :                   .FromJust());
   10868          24 :   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   10869             :                   .ToLocalChecked()
   10870             :                   ->Int32Value(context.local())
   10871             :                   .FromJust());
   10872          24 :   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   10873             :                   .ToLocalChecked()
   10874             :                   ->Int32Value(context.local())
   10875           6 :                   .FromJust());
   10876           6 : }
   10877             : 
   10878             : 
   10879             : // Regression test for issue 2457.
   10880       23724 : THREADED_TEST(HiddenPrototypeIdentityHash) {
   10881           6 :   LocalContext context;
   10882          12 :   v8::HandleScope handle_scope(context->GetIsolate());
   10883             : 
   10884           6 :   Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
   10885           6 :   t->SetHiddenPrototype(true);
   10886          24 :   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   10887           6 :   Local<Object> p = t->GetFunction(context.local())
   10888           6 :                         .ToLocalChecked()
   10889           6 :                         ->NewInstance(context.local())
   10890             :                         .ToLocalChecked();
   10891           6 :   Local<Object> o = Object::New(context->GetIsolate());
   10892          12 :   CHECK(o->SetPrototype(context.local(), p).FromJust());
   10893             : 
   10894           6 :   int hash = o->GetIdentityHash();
   10895             :   USE(hash);
   10896          18 :   CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
   10897          12 :   CHECK_EQ(hash, o->GetIdentityHash());
   10898           6 : }
   10899             : 
   10900             : 
   10901       23724 : THREADED_TEST(SetPrototype) {
   10902           6 :   LocalContext context;
   10903           6 :   v8::Isolate* isolate = context->GetIsolate();
   10904          12 :   v8::HandleScope handle_scope(isolate);
   10905             : 
   10906           6 :   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   10907          24 :   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   10908           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   10909           6 :   t1->SetHiddenPrototype(true);
   10910          24 :   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   10911           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   10912           6 :   t2->SetHiddenPrototype(true);
   10913          24 :   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   10914           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   10915          24 :   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   10916             : 
   10917           6 :   Local<v8::Object> o0 = t0->GetFunction(context.local())
   10918           6 :                              .ToLocalChecked()
   10919           6 :                              ->NewInstance(context.local())
   10920             :                              .ToLocalChecked();
   10921           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   10922           6 :                              .ToLocalChecked()
   10923           6 :                              ->NewInstance(context.local())
   10924             :                              .ToLocalChecked();
   10925           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   10926           6 :                              .ToLocalChecked()
   10927           6 :                              ->NewInstance(context.local())
   10928             :                              .ToLocalChecked();
   10929           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   10930           6 :                              .ToLocalChecked()
   10931           6 :                              ->NewInstance(context.local())
   10932             :                              .ToLocalChecked();
   10933             : 
   10934             :   // Setting the prototype on an object does not skip hidden prototypes.
   10935          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10936             :                   .ToLocalChecked()
   10937             :                   ->Int32Value(context.local())
   10938             :                   .FromJust());
   10939          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   10940          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10941             :                   .ToLocalChecked()
   10942             :                   ->Int32Value(context.local())
   10943             :                   .FromJust());
   10944          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10945             :                   .ToLocalChecked()
   10946             :                   ->Int32Value(context.local())
   10947             :                   .FromJust());
   10948          12 :   CHECK(o1->SetPrototype(context.local(), o2).FromJust());
   10949          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10950             :                   .ToLocalChecked()
   10951             :                   ->Int32Value(context.local())
   10952             :                   .FromJust());
   10953          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10954             :                   .ToLocalChecked()
   10955             :                   ->Int32Value(context.local())
   10956             :                   .FromJust());
   10957          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10958             :                   .ToLocalChecked()
   10959             :                   ->Int32Value(context.local())
   10960             :                   .FromJust());
   10961          12 :   CHECK(o2->SetPrototype(context.local(), o3).FromJust());
   10962          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   10963             :                   .ToLocalChecked()
   10964             :                   ->Int32Value(context.local())
   10965             :                   .FromJust());
   10966          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   10967             :                   .ToLocalChecked()
   10968             :                   ->Int32Value(context.local())
   10969             :                   .FromJust());
   10970          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   10971             :                   .ToLocalChecked()
   10972             :                   ->Int32Value(context.local())
   10973             :                   .FromJust());
   10974          24 :   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   10975             :                   .ToLocalChecked()
   10976             :                   ->Int32Value(context.local())
   10977             :                   .FromJust());
   10978             : 
   10979             :   // Getting the prototype of o0 should get the first visible one
   10980             :   // which is o3.  Therefore, z should not be defined on the prototype
   10981             :   // object.
   10982             :   Local<Value> proto =
   10983          18 :       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   10984           6 :   CHECK(proto->IsObject());
   10985          12 :   CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   10986             : 
   10987             :   // However, Object::GetPrototype ignores hidden prototype.
   10988           6 :   Local<Value> proto0 = o0->GetPrototype();
   10989           6 :   CHECK(proto0->IsObject());
   10990          12 :   CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   10991             : 
   10992           6 :   Local<Value> proto1 = o1->GetPrototype();
   10993           6 :   CHECK(proto1->IsObject());
   10994          12 :   CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
   10995             : 
   10996           6 :   Local<Value> proto2 = o2->GetPrototype();
   10997           6 :   CHECK(proto2->IsObject());
   10998          18 :   CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   10999           6 : }
   11000             : 
   11001             : 
   11002             : // Getting property names of an object with a prototype chain that
   11003             : // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   11004             : // crash the runtime.
   11005       23724 : THREADED_TEST(Regress91517) {
   11006           6 :   i::FLAG_allow_natives_syntax = true;
   11007           6 :   LocalContext context;
   11008           6 :   v8::Isolate* isolate = context->GetIsolate();
   11009          12 :   v8::HandleScope handle_scope(isolate);
   11010             : 
   11011           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11012           6 :   t1->SetHiddenPrototype(true);
   11013          24 :   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   11014           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11015           6 :   t2->SetHiddenPrototype(true);
   11016          24 :   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   11017          12 :   t2->InstanceTemplate()->Set(v8_str("objects"),
   11018          24 :                               v8::ObjectTemplate::New(isolate));
   11019          24 :   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   11020           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11021           6 :   t3->SetHiddenPrototype(true);
   11022          24 :   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   11023           6 :   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   11024          24 :   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   11025             : 
   11026             :   // Force dictionary-based properties.
   11027             :   i::ScopedVector<char> name_buf(1024);
   11028        6006 :   for (int i = 1; i <= 1000; i++) {
   11029        6000 :     i::SNPrintF(name_buf, "sdf%d", i);
   11030       24000 :     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   11031             :   }
   11032             : 
   11033           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11034           6 :                              .ToLocalChecked()
   11035           6 :                              ->NewInstance(context.local())
   11036             :                              .ToLocalChecked();
   11037           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11038           6 :                              .ToLocalChecked()
   11039           6 :                              ->NewInstance(context.local())
   11040             :                              .ToLocalChecked();
   11041           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11042           6 :                              .ToLocalChecked()
   11043           6 :                              ->NewInstance(context.local())
   11044             :                              .ToLocalChecked();
   11045           6 :   Local<v8::Object> o4 = t4->GetFunction(context.local())
   11046           6 :                              .ToLocalChecked()
   11047           6 :                              ->NewInstance(context.local())
   11048             :                              .ToLocalChecked();
   11049             : 
   11050             :   // Create prototype chain of hidden prototypes.
   11051          12 :   CHECK(o4->SetPrototype(context.local(), o3).FromJust());
   11052          12 :   CHECK(o3->SetPrototype(context.local(), o2).FromJust());
   11053          12 :   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11054             : 
   11055             :   // Call the runtime version of GetOwnPropertyNames() on the natively
   11056             :   // created object through JavaScript.
   11057          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
   11058             :   // PROPERTY_FILTER_NONE = 0
   11059             :   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11060             : 
   11061           6 :   ExpectInt32("names.length", 1006);
   11062             :   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11063             :   ExpectTrue("names.indexOf(\"boo\") >= 0");
   11064             :   ExpectTrue("names.indexOf(\"foo\") >= 0");
   11065             :   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   11066             :   ExpectTrue("names.indexOf(\"objects\") >= 0");
   11067             :   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   11068           6 :   ExpectFalse("names[1005] == undefined");
   11069           6 : }
   11070             : 
   11071             : 
   11072             : // Getting property names of an object with a hidden and inherited
   11073             : // prototype should not duplicate the accessor properties inherited.
   11074       23724 : THREADED_TEST(Regress269562) {
   11075           6 :   i::FLAG_allow_natives_syntax = true;
   11076           6 :   LocalContext context;
   11077          12 :   v8::HandleScope handle_scope(context->GetIsolate());
   11078             : 
   11079             :   Local<v8::FunctionTemplate> t1 =
   11080           6 :       v8::FunctionTemplate::New(context->GetIsolate());
   11081           6 :   t1->SetHiddenPrototype(true);
   11082             : 
   11083           6 :   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
   11084             :   i1->SetAccessor(v8_str("foo"),
   11085           6 :                   SimpleAccessorGetter, SimpleAccessorSetter);
   11086             :   i1->SetAccessor(v8_str("bar"),
   11087           6 :                   SimpleAccessorGetter, SimpleAccessorSetter);
   11088             :   i1->SetAccessor(v8_str("baz"),
   11089           6 :                   SimpleAccessorGetter, SimpleAccessorSetter);
   11090          18 :   i1->Set(v8_str("n1"), v8_num(1));
   11091          18 :   i1->Set(v8_str("n2"), v8_num(2));
   11092             : 
   11093           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11094           6 :                              .ToLocalChecked()
   11095           6 :                              ->NewInstance(context.local())
   11096             :                              .ToLocalChecked();
   11097             :   Local<v8::FunctionTemplate> t2 =
   11098           6 :       v8::FunctionTemplate::New(context->GetIsolate());
   11099           6 :   t2->SetHiddenPrototype(true);
   11100             : 
   11101             :   // Inherit from t1 and mark prototype as hidden.
   11102           6 :   t2->Inherit(t1);
   11103          24 :   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
   11104             : 
   11105           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11106           6 :                              .ToLocalChecked()
   11107           6 :                              ->NewInstance(context.local())
   11108             :                              .ToLocalChecked();
   11109          12 :   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11110             : 
   11111             :   v8::Local<v8::Symbol> sym =
   11112          12 :       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   11113          18 :   CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
   11114             :   o1->SetPrivate(context.local(),
   11115             :                  v8::Private::New(context->GetIsolate(), v8_str("h1")),
   11116          24 :                  v8::Integer::New(context->GetIsolate(), 2013))
   11117          12 :       .FromJust();
   11118             : 
   11119             :   // Call the runtime version of GetOwnPropertyNames() on
   11120             :   // the natively created object through JavaScript.
   11121          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
   11122          30 :   CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
   11123             :   // PROPERTY_FILTER_NONE = 0
   11124             :   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11125             : 
   11126           6 :   ExpectInt32("names.length", 7);
   11127             :   ExpectTrue("names.indexOf(\"foo\") >= 0");
   11128             :   ExpectTrue("names.indexOf(\"bar\") >= 0");
   11129             :   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11130             :   ExpectTrue("names.indexOf(\"n1\") >= 0");
   11131             :   ExpectTrue("names.indexOf(\"n2\") >= 0");
   11132             :   ExpectTrue("names.indexOf(sym) >= 0");
   11133           6 :   ExpectTrue("names.indexOf(\"mine\") >= 0");
   11134           6 : }
   11135             : 
   11136             : 
   11137       23724 : THREADED_TEST(FunctionReadOnlyPrototype) {
   11138           6 :   LocalContext context;
   11139           6 :   v8::Isolate* isolate = context->GetIsolate();
   11140          12 :   v8::HandleScope handle_scope(isolate);
   11141             : 
   11142           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11143          24 :   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11144           6 :   t1->ReadOnlyPrototype();
   11145          36 :   CHECK(context->Global()
   11146             :             ->Set(context.local(), v8_str("func1"),
   11147             :                   t1->GetFunction(context.local()).ToLocalChecked())
   11148             :             .FromJust());
   11149             :   // Configured value of ReadOnly flag.
   11150          18 :   CHECK(
   11151             :       CompileRun(
   11152             :           "(function() {"
   11153             :           "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   11154             :           "  return (descriptor['writable'] == false);"
   11155             :           "})()")
   11156             :           ->BooleanValue(context.local())
   11157             :           .FromJust());
   11158          18 :   CHECK_EQ(
   11159             :       42,
   11160             :       CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
   11161          18 :   CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
   11162             :                    ->Int32Value(context.local())
   11163             :                    .FromJust());
   11164             : 
   11165           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11166          24 :   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11167          36 :   CHECK(context->Global()
   11168             :             ->Set(context.local(), v8_str("func2"),
   11169             :                   t2->GetFunction(context.local()).ToLocalChecked())
   11170             :             .FromJust());
   11171             :   // Default value of ReadOnly flag.
   11172          18 :   CHECK(
   11173             :       CompileRun(
   11174             :           "(function() {"
   11175             :           "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   11176             :           "  return (descriptor['writable'] == true);"
   11177             :           "})()")
   11178             :           ->BooleanValue(context.local())
   11179             :           .FromJust());
   11180          18 :   CHECK_EQ(
   11181             :       42,
   11182           6 :       CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
   11183           6 : }
   11184             : 
   11185             : 
   11186       23724 : THREADED_TEST(SetPrototypeThrows) {
   11187           6 :   LocalContext context;
   11188           6 :   v8::Isolate* isolate = context->GetIsolate();
   11189          12 :   v8::HandleScope handle_scope(isolate);
   11190             : 
   11191           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11192             : 
   11193           6 :   Local<v8::Object> o0 = t->GetFunction(context.local())
   11194           6 :                              .ToLocalChecked()
   11195           6 :                              ->NewInstance(context.local())
   11196             :                              .ToLocalChecked();
   11197           6 :   Local<v8::Object> o1 = t->GetFunction(context.local())
   11198           6 :                              .ToLocalChecked()
   11199           6 :                              ->NewInstance(context.local())
   11200             :                              .ToLocalChecked();
   11201             : 
   11202          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11203             :   // If setting the prototype leads to the cycle, SetPrototype should
   11204             :   // return false and keep VM in sane state.
   11205          12 :   v8::TryCatch try_catch(isolate);
   11206          12 :   CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
   11207           6 :   CHECK(!try_catch.HasCaught());
   11208           6 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   11209             : 
   11210          18 :   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
   11211             :                    ->Int32Value(context.local())
   11212           6 :                    .FromJust());
   11213           6 : }
   11214             : 
   11215             : 
   11216       23724 : THREADED_TEST(FunctionRemovePrototype) {
   11217           6 :   LocalContext context;
   11218           6 :   v8::Isolate* isolate = context->GetIsolate();
   11219          12 :   v8::HandleScope handle_scope(isolate);
   11220             : 
   11221           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11222           6 :   t1->RemovePrototype();
   11223           6 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   11224           6 :   CHECK(!fun->IsConstructor());
   11225          30 :   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   11226          18 :   CHECK(!CompileRun("'prototype' in fun")
   11227             :              ->BooleanValue(context.local())
   11228             :              .FromJust());
   11229             : 
   11230          12 :   v8::TryCatch try_catch(isolate);
   11231             :   CompileRun("new fun()");
   11232           6 :   CHECK(try_catch.HasCaught());
   11233             : 
   11234           6 :   try_catch.Reset();
   11235          12 :   CHECK(fun->NewInstance(context.local()).IsEmpty());
   11236          12 :   CHECK(try_catch.HasCaught());
   11237           6 : }
   11238             : 
   11239             : 
   11240       23724 : THREADED_TEST(GetterSetterExceptions) {
   11241           6 :   LocalContext context;
   11242           6 :   v8::Isolate* isolate = context->GetIsolate();
   11243          12 :   v8::HandleScope handle_scope(isolate);
   11244             :   CompileRun(
   11245             :       "function Foo() { };"
   11246             :       "function Throw() { throw 5; };"
   11247             :       "var x = { };"
   11248             :       "x.__defineSetter__('set', Throw);"
   11249             :       "x.__defineGetter__('get', Throw);");
   11250             :   Local<v8::Object> x = Local<v8::Object>::Cast(
   11251          30 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
   11252          12 :   v8::TryCatch try_catch(isolate);
   11253          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11254             :             .IsNothing());
   11255          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11256          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11257             :             .IsNothing());
   11258          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11259          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11260             :             .IsNothing());
   11261          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11262          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11263             :             .IsNothing());
   11264          24 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11265           6 : }
   11266             : 
   11267             : 
   11268       23724 : THREADED_TEST(Constructor) {
   11269           6 :   LocalContext context;
   11270           6 :   v8::Isolate* isolate = context->GetIsolate();
   11271          12 :   v8::HandleScope handle_scope(isolate);
   11272           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11273           6 :   templ->SetClassName(v8_str("Fun"));
   11274           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11275          30 :   CHECK(
   11276             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11277           6 :   Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
   11278             :   i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
   11279           6 :   CHECK(obj->IsJSObject());
   11280             :   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   11281          18 :   CHECK(value->BooleanValue(context.local()).FromJust());
   11282           6 : }
   11283             : 
   11284             : 
   11285          48 : static void ConstructorCallback(
   11286          96 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11287          48 :   ApiTestFuzzer::Fuzz();
   11288             :   Local<Object> This;
   11289             : 
   11290          48 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   11291          48 :   if (args.IsConstructCall()) {
   11292             :     Local<Object> Holder = args.Holder();
   11293          48 :     This = Object::New(args.GetIsolate());
   11294          48 :     Local<Value> proto = Holder->GetPrototype();
   11295          48 :     if (proto->IsObject()) {
   11296          96 :       This->SetPrototype(context, proto).FromJust();
   11297             :     }
   11298             :   } else {
   11299             :     This = args.This();
   11300             :   }
   11301             : 
   11302         144 :   This->Set(context, v8_str("a"), args[0]).FromJust();
   11303             :   args.GetReturnValue().Set(This);
   11304          48 : }
   11305             : 
   11306             : 
   11307          48 : static void FakeConstructorCallback(
   11308          48 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   11309          48 :   ApiTestFuzzer::Fuzz();
   11310             :   args.GetReturnValue().Set(args[0]);
   11311          48 : }
   11312             : 
   11313             : 
   11314       23724 : THREADED_TEST(ConstructorForObject) {
   11315           6 :   LocalContext context;
   11316           6 :   v8::Isolate* isolate = context->GetIsolate();
   11317          12 :   v8::HandleScope handle_scope(isolate);
   11318             : 
   11319             :   {
   11320           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11321           6 :     instance_template->SetCallAsFunctionHandler(ConstructorCallback);
   11322             :     Local<Object> instance =
   11323           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11324          30 :     CHECK(context->Global()
   11325             :               ->Set(context.local(), v8_str("obj"), instance)
   11326             :               .FromJust());
   11327           6 :     v8::TryCatch try_catch(isolate);
   11328             :     Local<Value> value;
   11329           6 :     CHECK(!try_catch.HasCaught());
   11330             : 
   11331             :     // Call the Object's constructor with a 32-bit signed integer.
   11332             :     value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
   11333           6 :     CHECK(!try_catch.HasCaught());
   11334           6 :     CHECK(value->IsInt32());
   11335          12 :     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11336             : 
   11337           6 :     Local<Value> args1[] = {v8_num(28)};
   11338             :     Local<Value> value_obj1 =
   11339           6 :         instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
   11340           6 :     CHECK(value_obj1->IsObject());
   11341             :     Local<Object> object1 = Local<Object>::Cast(value_obj1);
   11342          18 :     value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
   11343           6 :     CHECK(value->IsInt32());
   11344           6 :     CHECK(!try_catch.HasCaught());
   11345          12 :     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11346             : 
   11347             :     // Call the Object's constructor with a String.
   11348             :     value =
   11349             :         CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
   11350           6 :     CHECK(!try_catch.HasCaught());
   11351           6 :     CHECK(value->IsString());
   11352             :     String::Utf8Value string_value1(
   11353          18 :         isolate, value->ToString(context.local()).ToLocalChecked());
   11354           6 :     CHECK_EQ(0, strcmp("tipli", *string_value1));
   11355             : 
   11356           6 :     Local<Value> args2[] = {v8_str("tipli")};
   11357             :     Local<Value> value_obj2 =
   11358           6 :         instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
   11359           6 :     CHECK(value_obj2->IsObject());
   11360             :     Local<Object> object2 = Local<Object>::Cast(value_obj2);
   11361          18 :     value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
   11362           6 :     CHECK(!try_catch.HasCaught());
   11363           6 :     CHECK(value->IsString());
   11364             :     String::Utf8Value string_value2(
   11365          18 :         isolate, value->ToString(context.local()).ToLocalChecked());
   11366           6 :     CHECK_EQ(0, strcmp("tipli", *string_value2));
   11367             : 
   11368             :     // Call the Object's constructor with a Boolean.
   11369             :     value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
   11370           6 :     CHECK(!try_catch.HasCaught());
   11371           6 :     CHECK(value->IsBoolean());
   11372          12 :     CHECK(value->BooleanValue(context.local()).FromJust());
   11373             : 
   11374             :     Local<Value> args3[] = {v8::True(isolate)};
   11375             :     Local<Value> value_obj3 =
   11376           6 :         instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
   11377           6 :     CHECK(value_obj3->IsObject());
   11378             :     Local<Object> object3 = Local<Object>::Cast(value_obj3);
   11379          18 :     value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
   11380           6 :     CHECK(!try_catch.HasCaught());
   11381           6 :     CHECK(value->IsBoolean());
   11382          12 :     CHECK(value->BooleanValue(context.local()).FromJust());
   11383             : 
   11384             :     // Call the Object's constructor with undefined.
   11385             :     Local<Value> args4[] = {v8::Undefined(isolate)};
   11386             :     Local<Value> value_obj4 =
   11387           6 :         instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
   11388           6 :     CHECK(value_obj4->IsObject());
   11389             :     Local<Object> object4 = Local<Object>::Cast(value_obj4);
   11390          18 :     value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
   11391           6 :     CHECK(!try_catch.HasCaught());
   11392           6 :     CHECK(value->IsUndefined());
   11393             : 
   11394             :     // Call the Object's constructor with null.
   11395             :     Local<Value> args5[] = {v8::Null(isolate)};
   11396             :     Local<Value> value_obj5 =
   11397           6 :         instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
   11398           6 :     CHECK(value_obj5->IsObject());
   11399             :     Local<Object> object5 = Local<Object>::Cast(value_obj5);
   11400          18 :     value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
   11401           6 :     CHECK(!try_catch.HasCaught());
   11402          12 :     CHECK(value->IsNull());
   11403             :   }
   11404             : 
   11405             :   // Check exception handling when there is no constructor set for the Object.
   11406             :   {
   11407           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11408             :     Local<Object> instance =
   11409          12 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11410          30 :     CHECK(context->Global()
   11411             :               ->Set(context.local(), v8_str("obj2"), instance)
   11412             :               .FromJust());
   11413           6 :     v8::TryCatch try_catch(isolate);
   11414             :     Local<Value> value;
   11415           6 :     CHECK(!try_catch.HasCaught());
   11416             : 
   11417             :     value = CompileRun("new obj2(28)");
   11418           6 :     CHECK(try_catch.HasCaught());
   11419          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11420           6 :     CHECK_EQ(0,
   11421             :              strcmp("TypeError: obj2 is not a constructor", *exception_value1));
   11422           6 :     try_catch.Reset();
   11423             : 
   11424           6 :     Local<Value> args[] = {v8_num(29)};
   11425          12 :     CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
   11426           6 :     CHECK(try_catch.HasCaught());
   11427          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11428           6 :     CHECK_EQ(
   11429             :         0, strcmp("TypeError: object is not a constructor", *exception_value2));
   11430          12 :     try_catch.Reset();
   11431             :   }
   11432             : 
   11433             :   // Check the case when constructor throws exception.
   11434             :   {
   11435           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11436           6 :     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11437             :     Local<Object> instance =
   11438           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11439          30 :     CHECK(context->Global()
   11440             :               ->Set(context.local(), v8_str("obj3"), instance)
   11441             :               .FromJust());
   11442           6 :     v8::TryCatch try_catch(isolate);
   11443             :     Local<Value> value;
   11444           6 :     CHECK(!try_catch.HasCaught());
   11445             : 
   11446             :     value = CompileRun("new obj3(22)");
   11447           6 :     CHECK(try_catch.HasCaught());
   11448          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11449           6 :     CHECK_EQ(0, strcmp("22", *exception_value1));
   11450           6 :     try_catch.Reset();
   11451             : 
   11452           6 :     Local<Value> args[] = {v8_num(23)};
   11453          12 :     CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
   11454           6 :     CHECK(try_catch.HasCaught());
   11455          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11456           6 :     CHECK_EQ(0, strcmp("23", *exception_value2));
   11457          12 :     try_catch.Reset();
   11458             :   }
   11459             : 
   11460             :   // Check whether constructor returns with an object or non-object.
   11461             :   {
   11462             :     Local<FunctionTemplate> function_template =
   11463           6 :         FunctionTemplate::New(isolate, FakeConstructorCallback);
   11464             :     Local<Function> function =
   11465          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   11466             :     Local<Object> instance1 = function;
   11467           6 :     CHECK(instance1->IsObject());
   11468           6 :     CHECK(instance1->IsFunction());
   11469          30 :     CHECK(context->Global()
   11470             :               ->Set(context.local(), v8_str("obj4"), instance1)
   11471             :               .FromJust());
   11472           6 :     v8::TryCatch try_catch(isolate);
   11473           6 :     CHECK(!try_catch.HasCaught());
   11474             : 
   11475             :     {
   11476             :       Local<Value> value = CompileRun("new obj4(28)");
   11477           6 :       CHECK(!try_catch.HasCaught());
   11478           6 :       CHECK(value->IsObject());
   11479             : 
   11480           6 :       Local<Value> args[] = {v8_num(28)};
   11481           6 :       value = instance1->CallAsConstructor(context.local(), 1, args)
   11482           6 :                   .ToLocalChecked();
   11483           6 :       CHECK(!try_catch.HasCaught());
   11484           6 :       CHECK(value->IsObject());
   11485             :     }
   11486             : 
   11487             :     Local<Value> proxy = CompileRun("proxy = new Proxy({},{})");
   11488           6 :     CHECK(!try_catch.HasCaught());
   11489           6 :     CHECK(proxy->IsProxy());
   11490             : 
   11491             :     {
   11492             :       Local<Value> value = CompileRun("new obj4(proxy)");
   11493           6 :       CHECK(!try_catch.HasCaught());
   11494           6 :       CHECK(value->IsProxy());
   11495           6 :       CHECK(value->SameValue(proxy));
   11496             : 
   11497           6 :       Local<Value> args[] = {proxy};
   11498           6 :       value = instance1->CallAsConstructor(context.local(), 1, args)
   11499           6 :                   .ToLocalChecked();
   11500           6 :       CHECK(!try_catch.HasCaught());
   11501           6 :       CHECK(value->SameValue(proxy));
   11502             :     }
   11503             : 
   11504           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11505           6 :     instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
   11506             :     Local<Object> instance2 =
   11507           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11508           6 :     CHECK(instance2->IsObject());
   11509           6 :     CHECK(instance2->IsFunction());
   11510          30 :     CHECK(context->Global()
   11511             :               ->Set(context.local(), v8_str("obj5"), instance2)
   11512             :               .FromJust());
   11513           6 :     CHECK(!try_catch.HasCaught());
   11514             : 
   11515             :     {
   11516             :       Local<Value> value = CompileRun("new obj5(28)");
   11517           6 :       CHECK(!try_catch.HasCaught());
   11518           6 :       CHECK(!value->IsObject());
   11519             : 
   11520           6 :       Local<Value> args[] = {v8_num(28)};
   11521           6 :       value = instance2->CallAsConstructor(context.local(), 1, args)
   11522           6 :                   .ToLocalChecked();
   11523           6 :       CHECK(!try_catch.HasCaught());
   11524           6 :       CHECK(!value->IsObject());
   11525             :     }
   11526             : 
   11527             :     {
   11528             :       Local<Value> value = CompileRun("new obj5(proxy)");
   11529           6 :       CHECK(!try_catch.HasCaught());
   11530           6 :       CHECK(value->IsProxy());
   11531           6 :       CHECK(value->SameValue(proxy));
   11532             : 
   11533           6 :       Local<Value> args[] = {proxy};
   11534           6 :       value = instance2->CallAsConstructor(context.local(), 1, args)
   11535           6 :                   .ToLocalChecked();
   11536           6 :       CHECK(!try_catch.HasCaught());
   11537           6 :       CHECK(value->SameValue(proxy));
   11538           6 :     }
   11539           6 :   }
   11540           6 : }
   11541             : 
   11542             : 
   11543       23724 : THREADED_TEST(FunctionDescriptorException) {
   11544           6 :   LocalContext context;
   11545           6 :   v8::Isolate* isolate = context->GetIsolate();
   11546          12 :   v8::HandleScope handle_scope(isolate);
   11547           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11548           6 :   templ->SetClassName(v8_str("Fun"));
   11549           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11550          30 :   CHECK(
   11551             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11552             :   Local<Value> value = CompileRun(
   11553             :       "function test() {"
   11554             :       "  try {"
   11555             :       "    (new Fun()).blah()"
   11556             :       "  } catch (e) {"
   11557             :       "    var str = String(e);"
   11558             :       // "    if (str.indexOf('TypeError') == -1) return 1;"
   11559             :       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   11560             :       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   11561             :       "    return 0;"
   11562             :       "  }"
   11563             :       "  return 4;"
   11564             :       "}"
   11565             :       "test();");
   11566          18 :   CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
   11567           6 : }
   11568             : 
   11569             : 
   11570       23724 : THREADED_TEST(EvalAliasedDynamic) {
   11571           6 :   LocalContext current;
   11572          12 :   v8::HandleScope scope(current->GetIsolate());
   11573             : 
   11574             :   // Tests where aliased eval can only be resolved dynamically.
   11575             :   Local<Script> script = v8_compile(
   11576             :       "function f(x) { "
   11577             :       "  var foo = 2;"
   11578             :       "  with (x) { return eval('foo'); }"
   11579             :       "}"
   11580             :       "foo = 0;"
   11581             :       "result1 = f(new Object());"
   11582             :       "result2 = f(this);"
   11583             :       "var x = new Object();"
   11584             :       "x.eval = function(x) { return 1; };"
   11585             :       "result3 = f(x);");
   11586           6 :   script->Run(current.local()).ToLocalChecked();
   11587          36 :   CHECK_EQ(2, current->Global()
   11588             :                   ->Get(current.local(), v8_str("result1"))
   11589             :                   .ToLocalChecked()
   11590             :                   ->Int32Value(current.local())
   11591             :                   .FromJust());
   11592          36 :   CHECK_EQ(0, current->Global()
   11593             :                   ->Get(current.local(), v8_str("result2"))
   11594             :                   .ToLocalChecked()
   11595             :                   ->Int32Value(current.local())
   11596             :                   .FromJust());
   11597          36 :   CHECK_EQ(1, current->Global()
   11598             :                   ->Get(current.local(), v8_str("result3"))
   11599             :                   .ToLocalChecked()
   11600             :                   ->Int32Value(current.local())
   11601             :                   .FromJust());
   11602             : 
   11603          12 :   v8::TryCatch try_catch(current->GetIsolate());
   11604             :   script = v8_compile(
   11605             :       "function f(x) { "
   11606             :       "  var bar = 2;"
   11607             :       "  with (x) { return eval('bar'); }"
   11608             :       "}"
   11609             :       "result4 = f(this)");
   11610           6 :   script->Run(current.local()).ToLocalChecked();
   11611           6 :   CHECK(!try_catch.HasCaught());
   11612          36 :   CHECK_EQ(2, current->Global()
   11613             :                   ->Get(current.local(), v8_str("result4"))
   11614             :                   .ToLocalChecked()
   11615             :                   ->Int32Value(current.local())
   11616             :                   .FromJust());
   11617             : 
   11618          12 :   try_catch.Reset();
   11619           6 : }
   11620             : 
   11621             : 
   11622       23724 : THREADED_TEST(CrossEval) {
   11623           6 :   v8::HandleScope scope(CcTest::isolate());
   11624          12 :   LocalContext other;
   11625          12 :   LocalContext current;
   11626             : 
   11627           6 :   Local<String> token = v8_str("<security token>");
   11628           6 :   other->SetSecurityToken(token);
   11629           6 :   current->SetSecurityToken(token);
   11630             : 
   11631             :   // Set up reference from current to other.
   11632          36 :   CHECK(current->Global()
   11633             :             ->Set(current.local(), v8_str("other"), other->Global())
   11634             :             .FromJust());
   11635             : 
   11636             :   // Check that new variables are introduced in other context.
   11637             :   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   11638           6 :   script->Run(current.local()).ToLocalChecked();
   11639             :   Local<Value> foo =
   11640          30 :       other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
   11641          12 :   CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
   11642          30 :   CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
   11643             : 
   11644             :   // Check that writing to non-existing properties introduces them in
   11645             :   // the other context.
   11646             :   script = v8_compile("other.eval('na = 1234')");
   11647           6 :   script->Run(current.local()).ToLocalChecked();
   11648          36 :   CHECK_EQ(1234, other->Global()
   11649             :                      ->Get(current.local(), v8_str("na"))
   11650             :                      .ToLocalChecked()
   11651             :                      ->Int32Value(other.local())
   11652             :                      .FromJust());
   11653          30 :   CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
   11654             : 
   11655             :   // Check that global variables in current context are not visible in other
   11656             :   // context.
   11657          12 :   v8::TryCatch try_catch(CcTest::isolate());
   11658             :   script = v8_compile("var bar = 42; other.eval('bar');");
   11659          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11660           6 :   CHECK(try_catch.HasCaught());
   11661           6 :   try_catch.Reset();
   11662             : 
   11663             :   // Check that local variables in current context are not visible in other
   11664             :   // context.
   11665             :   script = v8_compile(
   11666             :       "(function() { "
   11667             :       "  var baz = 87;"
   11668             :       "  return other.eval('baz');"
   11669             :       "})();");
   11670          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11671           6 :   CHECK(try_catch.HasCaught());
   11672           6 :   try_catch.Reset();
   11673             : 
   11674             :   // Check that global variables in the other environment are visible
   11675             :   // when evaluting code.
   11676          30 :   CHECK(other->Global()
   11677             :             ->Set(other.local(), v8_str("bis"), v8_num(1234))
   11678             :             .FromJust());
   11679             :   script = v8_compile("other.eval('bis')");
   11680          18 :   CHECK_EQ(1234, script->Run(current.local())
   11681             :                      .ToLocalChecked()
   11682             :                      ->Int32Value(current.local())
   11683             :                      .FromJust());
   11684           6 :   CHECK(!try_catch.HasCaught());
   11685             : 
   11686             :   // Check that the 'this' pointer points to the global object evaluating
   11687             :   // code.
   11688          36 :   CHECK(other->Global()
   11689             :             ->Set(current.local(), v8_str("t"), other->Global())
   11690             :             .FromJust());
   11691             :   script = v8_compile("other.eval('this == t')");
   11692           6 :   Local<Value> result = script->Run(current.local()).ToLocalChecked();
   11693           6 :   CHECK(result->IsTrue());
   11694           6 :   CHECK(!try_catch.HasCaught());
   11695             : 
   11696             :   // Check that variables introduced in with-statement are not visible in
   11697             :   // other context.
   11698             :   script = v8_compile("with({x:2}){other.eval('x')}");
   11699          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11700           6 :   CHECK(try_catch.HasCaught());
   11701           6 :   try_catch.Reset();
   11702             : 
   11703             :   // Check that you cannot use 'eval.call' with another object than the
   11704             :   // current global object.
   11705             :   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   11706          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11707          12 :   CHECK(try_catch.HasCaught());
   11708           6 : }
   11709             : 
   11710             : 
   11711             : // Test that calling eval in a context which has been detached from
   11712             : // its global proxy works.
   11713       23724 : THREADED_TEST(EvalInDetachedGlobal) {
   11714           6 :   v8::Isolate* isolate = CcTest::isolate();
   11715           6 :   v8::HandleScope scope(isolate);
   11716             : 
   11717           6 :   v8::Local<Context> context0 = Context::New(isolate);
   11718           6 :   v8::Local<Context> context1 = Context::New(isolate);
   11719           6 :   Local<String> token = v8_str("<security token>");
   11720           6 :   context0->SetSecurityToken(token);
   11721           6 :   context1->SetSecurityToken(token);
   11722             : 
   11723             :   // Set up function in context0 that uses eval from context0.
   11724           6 :   context0->Enter();
   11725             :   v8::Local<v8::Value> fun = CompileRun(
   11726             :       "var x = 42;"
   11727             :       "(function() {"
   11728             :       "  var e = eval;"
   11729             :       "  return function(s) { return e(s); }"
   11730           6 :       "})()");
   11731           6 :   context0->Exit();
   11732             : 
   11733             :   // Put the function into context1 and call it before and after
   11734             :   // detaching the global.  Before detaching, the call succeeds and
   11735             :   // after detaching undefined is returned.
   11736           6 :   context1->Enter();
   11737          24 :   CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
   11738             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   11739          12 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11740           6 :   context0->DetachGlobal();
   11741             :   x_value = CompileRun("fun('x')");
   11742           6 :   CHECK(x_value->IsUndefined());
   11743           6 :   context1->Exit();
   11744           6 : }
   11745             : 
   11746             : 
   11747       23724 : THREADED_TEST(CrossLazyLoad) {
   11748           6 :   v8::HandleScope scope(CcTest::isolate());
   11749          12 :   LocalContext other;
   11750          12 :   LocalContext current;
   11751             : 
   11752           6 :   Local<String> token = v8_str("<security token>");
   11753           6 :   other->SetSecurityToken(token);
   11754           6 :   current->SetSecurityToken(token);
   11755             : 
   11756             :   // Set up reference from current to other.
   11757          36 :   CHECK(current->Global()
   11758             :             ->Set(current.local(), v8_str("other"), other->Global())
   11759             :             .FromJust());
   11760             : 
   11761             :   // Trigger lazy loading in other context.
   11762             :   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11763           6 :   Local<Value> value = script->Run(current.local()).ToLocalChecked();
   11764          18 :   CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
   11765           6 : }
   11766             : 
   11767             : 
   11768         102 : static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11769          48 :   ApiTestFuzzer::Fuzz();
   11770          48 :   if (args.IsConstructCall()) {
   11771           6 :     if (args[0]->IsInt32()) {
   11772             :       args.GetReturnValue().Set(
   11773             :           v8_num(-args[0]
   11774           6 :                       ->Int32Value(args.GetIsolate()->GetCurrentContext())
   11775          18 :                       .FromJust()));
   11776          54 :       return;
   11777             :     }
   11778             :   }
   11779             : 
   11780             :   args.GetReturnValue().Set(args[0]);
   11781             : }
   11782             : 
   11783             : 
   11784             : // Test that a call handler can be set for objects which will allow
   11785             : // non-function objects created through the API to be called as
   11786             : // functions.
   11787       23724 : THREADED_TEST(CallAsFunction) {
   11788           6 :   LocalContext context;
   11789           6 :   v8::Isolate* isolate = context->GetIsolate();
   11790          12 :   v8::HandleScope scope(isolate);
   11791             : 
   11792             :   {
   11793           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11794           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11795           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   11796           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11797           6 :                                      .ToLocalChecked()
   11798           6 :                                      ->NewInstance(context.local())
   11799             :                                      .ToLocalChecked();
   11800          30 :     CHECK(context->Global()
   11801             :               ->Set(context.local(), v8_str("obj"), instance)
   11802             :               .FromJust());
   11803           6 :     v8::TryCatch try_catch(isolate);
   11804             :     Local<Value> value;
   11805           6 :     CHECK(!try_catch.HasCaught());
   11806             : 
   11807             :     value = CompileRun("obj(42)");
   11808           6 :     CHECK(!try_catch.HasCaught());
   11809          12 :     CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11810             : 
   11811             :     value = CompileRun("(function(o){return o(49)})(obj)");
   11812           6 :     CHECK(!try_catch.HasCaught());
   11813          12 :     CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
   11814             : 
   11815             :     // test special case of call as function
   11816             :     value = CompileRun("[obj]['0'](45)");
   11817           6 :     CHECK(!try_catch.HasCaught());
   11818          12 :     CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
   11819             : 
   11820             :     value = CompileRun(
   11821             :         "obj.call = Function.prototype.call;"
   11822             :         "obj.call(null, 87)");
   11823           6 :     CHECK(!try_catch.HasCaught());
   11824          12 :     CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
   11825             : 
   11826             :     // Regression tests for bug #1116356: Calling call through call/apply
   11827             :     // must work for non-function receivers.
   11828             :     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11829             :     value = CompileRun(apply_99);
   11830           6 :     CHECK(!try_catch.HasCaught());
   11831          12 :     CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
   11832             : 
   11833             :     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11834             :     value = CompileRun(call_17);
   11835           6 :     CHECK(!try_catch.HasCaught());
   11836          12 :     CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
   11837             : 
   11838             :     // Check that the call-as-function handler can be called through
   11839             :     // new.
   11840             :     value = CompileRun("new obj(43)");
   11841           6 :     CHECK(!try_catch.HasCaught());
   11842          12 :     CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
   11843             : 
   11844             :     // Check that the call-as-function handler can be called through
   11845             :     // the API.
   11846           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11847          12 :     value = instance->CallAsFunction(context.local(), instance, 1, args)
   11848           6 :                 .ToLocalChecked();
   11849           6 :     CHECK(!try_catch.HasCaught());
   11850          12 :     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11851             :   }
   11852             : 
   11853             :   {
   11854           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11855           6 :     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11856             :     USE(instance_template);
   11857           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11858           6 :                                      .ToLocalChecked()
   11859           6 :                                      ->NewInstance(context.local())
   11860             :                                      .ToLocalChecked();
   11861          30 :     CHECK(context->Global()
   11862             :               ->Set(context.local(), v8_str("obj2"), instance)
   11863             :               .FromJust());
   11864           6 :     v8::TryCatch try_catch(isolate);
   11865             :     Local<Value> value;
   11866           6 :     CHECK(!try_catch.HasCaught());
   11867             : 
   11868             :     // Call an object without call-as-function handler through the JS
   11869             :     value = CompileRun("obj2(28)");
   11870           6 :     CHECK(value.IsEmpty());
   11871           6 :     CHECK(try_catch.HasCaught());
   11872          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11873             :     // TODO(verwaest): Better message
   11874           6 :     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
   11875           6 :     try_catch.Reset();
   11876             : 
   11877             :     // Call an object without call-as-function handler through the API
   11878             :     value = CompileRun("obj2(28)");
   11879           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11880          12 :     CHECK(
   11881             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11882           6 :     CHECK(try_catch.HasCaught());
   11883          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11884           6 :     CHECK_EQ(0,
   11885             :              strcmp("TypeError: object is not a function", *exception_value2));
   11886          12 :     try_catch.Reset();
   11887             :   }
   11888             : 
   11889             :   {
   11890           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11891           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11892           6 :     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11893           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11894           6 :                                      .ToLocalChecked()
   11895           6 :                                      ->NewInstance(context.local())
   11896             :                                      .ToLocalChecked();
   11897          30 :     CHECK(context->Global()
   11898             :               ->Set(context.local(), v8_str("obj3"), instance)
   11899             :               .FromJust());
   11900           6 :     v8::TryCatch try_catch(isolate);
   11901             :     Local<Value> value;
   11902           6 :     CHECK(!try_catch.HasCaught());
   11903             : 
   11904             :     // Catch the exception which is thrown by call-as-function handler
   11905             :     value = CompileRun("obj3(22)");
   11906           6 :     CHECK(try_catch.HasCaught());
   11907          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11908           6 :     CHECK_EQ(0, strcmp("22", *exception_value1));
   11909           6 :     try_catch.Reset();
   11910             : 
   11911           6 :     v8::Local<Value> args[] = {v8_num(23)};
   11912          12 :     CHECK(
   11913             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11914           6 :     CHECK(try_catch.HasCaught());
   11915          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11916           6 :     CHECK_EQ(0, strcmp("23", *exception_value2));
   11917          12 :     try_catch.Reset();
   11918             :   }
   11919             : 
   11920             :   {
   11921           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11922           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11923           6 :     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11924           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11925           6 :                                      .ToLocalChecked()
   11926           6 :                                      ->NewInstance(context.local())
   11927             :                                      .ToLocalChecked();
   11928             : 
   11929             :     Local<v8::Value> a1 =
   11930             :         instance
   11931             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11932          12 :                              nullptr)
   11933           6 :             .ToLocalChecked();
   11934           6 :     CHECK(a1->StrictEquals(instance));
   11935             :     Local<v8::Value> a2 =
   11936          12 :         instance->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11937           6 :             .ToLocalChecked();
   11938           6 :     CHECK(a2->StrictEquals(instance));
   11939             :     Local<v8::Value> a3 =
   11940           6 :         instance->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11941           6 :             .ToLocalChecked();
   11942           6 :     CHECK(a3->StrictEquals(instance));
   11943             :     Local<v8::Value> a4 =
   11944          18 :         instance->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11945           6 :             .ToLocalChecked();
   11946           6 :     CHECK(a4->StrictEquals(instance));
   11947             :     Local<v8::Value> a5 =
   11948          12 :         instance->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11949           6 :             .ToLocalChecked();
   11950           6 :     CHECK(a5->StrictEquals(instance));
   11951             :   }
   11952             : 
   11953             :   {
   11954             :     CompileRun(
   11955             :         "function ReturnThisSloppy() {"
   11956             :         "  return this;"
   11957             :         "}"
   11958             :         "function ReturnThisStrict() {"
   11959             :         "  'use strict';"
   11960             :         "  return this;"
   11961             :         "}");
   11962             :     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   11963             :         context->Global()
   11964          24 :             ->Get(context.local(), v8_str("ReturnThisSloppy"))
   11965           6 :             .ToLocalChecked());
   11966             :     Local<Function> ReturnThisStrict = Local<Function>::Cast(
   11967             :         context->Global()
   11968          24 :             ->Get(context.local(), v8_str("ReturnThisStrict"))
   11969           6 :             .ToLocalChecked());
   11970             : 
   11971             :     Local<v8::Value> a1 =
   11972             :         ReturnThisSloppy
   11973             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11974          12 :                              nullptr)
   11975           6 :             .ToLocalChecked();
   11976          12 :     CHECK(a1->StrictEquals(context->Global()));
   11977             :     Local<v8::Value> a2 =
   11978             :         ReturnThisSloppy
   11979          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11980           6 :             .ToLocalChecked();
   11981          12 :     CHECK(a2->StrictEquals(context->Global()));
   11982             :     Local<v8::Value> a3 =
   11983             :         ReturnThisSloppy
   11984           6 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11985           6 :             .ToLocalChecked();
   11986           6 :     CHECK(a3->IsNumberObject());
   11987           6 :     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   11988             :     Local<v8::Value> a4 =
   11989             :         ReturnThisSloppy
   11990          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11991           6 :             .ToLocalChecked();
   11992           6 :     CHECK(a4->IsStringObject());
   11993          18 :     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   11994             :     Local<v8::Value> a5 =
   11995             :         ReturnThisSloppy
   11996          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11997           6 :             .ToLocalChecked();
   11998           6 :     CHECK(a5->IsBooleanObject());
   11999           6 :     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   12000             : 
   12001             :     Local<v8::Value> a6 =
   12002             :         ReturnThisStrict
   12003             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   12004          12 :                              nullptr)
   12005           6 :             .ToLocalChecked();
   12006           6 :     CHECK(a6->IsUndefined());
   12007             :     Local<v8::Value> a7 =
   12008             :         ReturnThisStrict
   12009          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   12010           6 :             .ToLocalChecked();
   12011           6 :     CHECK(a7->IsNull());
   12012             :     Local<v8::Value> a8 =
   12013             :         ReturnThisStrict
   12014           6 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   12015           6 :             .ToLocalChecked();
   12016           6 :     CHECK(a8->StrictEquals(v8_num(42)));
   12017             :     Local<v8::Value> a9 =
   12018             :         ReturnThisStrict
   12019          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   12020           6 :             .ToLocalChecked();
   12021          12 :     CHECK(a9->StrictEquals(v8_str("hello")));
   12022             :     Local<v8::Value> a10 =
   12023             :         ReturnThisStrict
   12024          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   12025           6 :             .ToLocalChecked();
   12026           6 :     CHECK(a10->StrictEquals(v8::True(isolate)));
   12027           6 :   }
   12028           6 : }
   12029             : 
   12030             : 
   12031             : // Check whether a non-function object is callable.
   12032       23724 : THREADED_TEST(CallableObject) {
   12033           6 :   LocalContext context;
   12034           6 :   v8::Isolate* isolate = context->GetIsolate();
   12035          12 :   v8::HandleScope scope(isolate);
   12036             : 
   12037             :   {
   12038           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   12039           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   12040             :     Local<Object> instance =
   12041           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   12042           6 :     v8::TryCatch try_catch(isolate);
   12043             : 
   12044           6 :     CHECK(instance->IsCallable());
   12045           6 :     CHECK(!try_catch.HasCaught());
   12046             :   }
   12047             : 
   12048             :   {
   12049           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   12050             :     Local<Object> instance =
   12051          12 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   12052           6 :     v8::TryCatch try_catch(isolate);
   12053             : 
   12054           6 :     CHECK(!instance->IsCallable());
   12055           6 :     CHECK(!try_catch.HasCaught());
   12056             :   }
   12057             : 
   12058             :   {
   12059             :     Local<FunctionTemplate> function_template =
   12060           6 :         FunctionTemplate::New(isolate, call_as_function);
   12061             :     Local<Function> function =
   12062          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   12063             :     Local<Object> instance = function;
   12064           6 :     v8::TryCatch try_catch(isolate);
   12065             : 
   12066           6 :     CHECK(instance->IsCallable());
   12067           6 :     CHECK(!try_catch.HasCaught());
   12068             :   }
   12069             : 
   12070             :   {
   12071           6 :     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   12072             :     Local<Function> function =
   12073          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   12074             :     Local<Object> instance = function;
   12075           6 :     v8::TryCatch try_catch(isolate);
   12076             : 
   12077           6 :     CHECK(instance->IsCallable());
   12078           6 :     CHECK(!try_catch.HasCaught());
   12079           6 :   }
   12080           6 : }
   12081             : 
   12082             : 
   12083       23724 : THREADED_TEST(Regress567998) {
   12084           6 :   LocalContext env;
   12085          12 :   v8::HandleScope scope(env->GetIsolate());
   12086             : 
   12087             :   Local<v8::FunctionTemplate> desc =
   12088           6 :       v8::FunctionTemplate::New(env->GetIsolate());
   12089          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   12090          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
   12091             : 
   12092           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   12093           6 :                               .ToLocalChecked()
   12094           6 :                               ->NewInstance(env.local())
   12095             :                               .ToLocalChecked();
   12096          30 :   CHECK(
   12097             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   12098             : 
   12099           6 :   ExpectString("undetectable.toString()", "[object Object]");
   12100           6 :   ExpectString("typeof undetectable", "undefined");
   12101           6 :   ExpectString("typeof(undetectable)", "undefined");
   12102           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
   12103           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
   12104           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   12105           6 :   ExpectBoolean("!undetectable", true);
   12106             : 
   12107           6 :   ExpectObject("true&&undetectable", obj);
   12108           6 :   ExpectBoolean("false&&undetectable", false);
   12109           6 :   ExpectBoolean("true||undetectable", true);
   12110           6 :   ExpectObject("false||undetectable", obj);
   12111             : 
   12112           6 :   ExpectObject("undetectable&&true", obj);
   12113           6 :   ExpectObject("undetectable&&false", obj);
   12114           6 :   ExpectBoolean("undetectable||true", true);
   12115           6 :   ExpectBoolean("undetectable||false", false);
   12116             : 
   12117           6 :   ExpectBoolean("undetectable==null", true);
   12118           6 :   ExpectBoolean("null==undetectable", true);
   12119           6 :   ExpectBoolean("undetectable==undefined", true);
   12120           6 :   ExpectBoolean("undefined==undetectable", true);
   12121           6 :   ExpectBoolean("undetectable==undetectable", true);
   12122             : 
   12123           6 :   ExpectBoolean("undetectable===null", false);
   12124           6 :   ExpectBoolean("null===undetectable", false);
   12125           6 :   ExpectBoolean("undetectable===undefined", false);
   12126           6 :   ExpectBoolean("undefined===undetectable", false);
   12127          12 :   ExpectBoolean("undetectable===undetectable", true);
   12128           6 : }
   12129             : 
   12130             : 
   12131        1206 : static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   12132        1206 :   v8::HandleScope scope(isolate);
   12133        1206 :   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   12134      600000 :   for (int i = 0; i < iterations; i++) {
   12135      600000 :     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   12136             :   }
   12137        1200 :   return Recurse(isolate, depth - 1, iterations);
   12138             : }
   12139             : 
   12140             : 
   12141       23724 : THREADED_TEST(HandleIteration) {
   12142             :   static const int kIterations = 500;
   12143             :   static const int kNesting = 200;
   12144           6 :   LocalContext context;
   12145           6 :   v8::Isolate* isolate = context->GetIsolate();
   12146          12 :   v8::HandleScope scope0(isolate);
   12147           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12148             :   {
   12149           6 :     v8::HandleScope scope1(isolate);
   12150           6 :     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12151        3006 :     for (int i = 0; i < kIterations; i++) {
   12152        3000 :       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12153        3000 :       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   12154             :     }
   12155             : 
   12156           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12157             :     {
   12158           6 :       v8::HandleScope scope2(CcTest::isolate());
   12159        3006 :       for (int j = 0; j < kIterations; j++) {
   12160        3000 :         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12161        3000 :         CHECK_EQ(j + 1 + kIterations,
   12162             :                  v8::HandleScope::NumberOfHandles(isolate));
   12163           6 :       }
   12164             :     }
   12165           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12166             :   }
   12167           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12168          12 :   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   12169           6 : }
   12170             : 
   12171             : 
   12172        4994 : static void InterceptorCallICFastApi(
   12173             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12174        4994 :   ApiTestFuzzer::Fuzz();
   12175        4994 :   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   12176             :   int* call_count =
   12177        4994 :       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   12178        4994 :   ++(*call_count);
   12179        4994 :   if ((*call_count) % 20 == 0) {
   12180         231 :     CcTest::CollectAllGarbage();
   12181             :   }
   12182        4994 : }
   12183             : 
   12184        2200 : static void FastApiCallback_TrivialSignature(
   12185        8800 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12186        2200 :   ApiTestFuzzer::Fuzz();
   12187        2200 :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   12188        2200 :   v8::Isolate* isolate = CcTest::isolate();
   12189        2200 :   CHECK_EQ(isolate, args.GetIsolate());
   12190        6600 :   CHECK(args.This()
   12191             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12192             :             .FromJust());
   12193        8800 :   CHECK(args.Data()
   12194             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12195             :             .FromJust());
   12196             :   args.GetReturnValue().Set(
   12197        8800 :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12198        2200 : }
   12199             : 
   12200        6127 : static void FastApiCallback_SimpleSignature(
   12201       30635 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12202        6127 :   ApiTestFuzzer::Fuzz();
   12203        6127 :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   12204        6127 :   v8::Isolate* isolate = CcTest::isolate();
   12205        6127 :   CHECK_EQ(isolate, args.GetIsolate());
   12206       24508 :   CHECK(args.This()
   12207             :             ->GetPrototype()
   12208             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12209             :             .FromJust());
   12210       24508 :   CHECK(args.Data()
   12211             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12212             :             .FromJust());
   12213             :   // Note, we're using HasRealNamedProperty instead of Has to avoid
   12214             :   // invoking the interceptor again.
   12215       24508 :   CHECK(args.Holder()
   12216             :             ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
   12217             :             .FromJust());
   12218             :   args.GetReturnValue().Set(
   12219       24508 :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12220        6127 : }
   12221             : 
   12222             : 
   12223             : // Helper to maximize the odds of object moving.
   12224         291 : static void GenerateSomeGarbage() {
   12225             :   CompileRun(
   12226             :       "var garbage;"
   12227             :       "for (var i = 0; i < 1000; i++) {"
   12228             :       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   12229             :       "}"
   12230             :       "garbage = undefined;");
   12231         291 : }
   12232             : 
   12233             : 
   12234         180 : void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12235             :   static int count = 0;
   12236         180 :   if (count++ % 3 == 0) {
   12237          60 :     CcTest::CollectAllGarbage();
   12238             :     // This should move the stub
   12239          60 :     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   12240             :   }
   12241         180 : }
   12242             : 
   12243             : 
   12244       23724 : THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   12245           6 :   LocalContext context;
   12246           6 :   v8::Isolate* isolate = context->GetIsolate();
   12247          12 :   v8::HandleScope scope(isolate);
   12248             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12249           6 :       v8::ObjectTemplate::New(isolate);
   12250             :   nativeobject_templ->Set(isolate, "callback",
   12251             :                           v8::FunctionTemplate::New(isolate,
   12252          12 :                                                     DirectApiCallback));
   12253             :   v8::Local<v8::Object> nativeobject_obj =
   12254           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12255          30 :   CHECK(context->Global()
   12256             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12257             :             .FromJust());
   12258             :   // call the api function multiple times to ensure direct call stub creation.
   12259             :   CompileRun(
   12260             :         "function f() {"
   12261             :         "  for (var i = 1; i <= 30; i++) {"
   12262             :         "    nativeobject.callback();"
   12263             :         "  }"
   12264             :         "}"
   12265           6 :         "f();");
   12266           6 : }
   12267             : 
   12268             : 
   12269          30 : void ThrowingDirectApiCallback(
   12270          30 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12271          60 :   args.GetIsolate()->ThrowException(v8_str("g"));
   12272          30 : }
   12273             : 
   12274             : 
   12275       23724 : THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   12276           6 :   LocalContext context;
   12277           6 :   v8::Isolate* isolate = context->GetIsolate();
   12278          12 :   v8::HandleScope scope(isolate);
   12279             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12280           6 :       v8::ObjectTemplate::New(isolate);
   12281             :   nativeobject_templ->Set(isolate, "callback",
   12282             :                           v8::FunctionTemplate::New(isolate,
   12283          12 :                                                     ThrowingDirectApiCallback));
   12284             :   v8::Local<v8::Object> nativeobject_obj =
   12285           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12286          30 :   CHECK(context->Global()
   12287             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12288             :             .FromJust());
   12289             :   // call the api function multiple times to ensure direct call stub creation.
   12290             :   v8::Local<Value> result = CompileRun(
   12291             :       "var result = '';"
   12292             :       "function f() {"
   12293             :       "  for (var i = 1; i <= 5; i++) {"
   12294             :       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   12295             :       "  }"
   12296             :       "}"
   12297           6 :       "f(); result;");
   12298          24 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12299           6 : }
   12300             : 
   12301             : 
   12302             : static int p_getter_count_3;
   12303             : 
   12304             : 
   12305         341 : static Local<Value> DoDirectGetter() {
   12306         341 :   if (++p_getter_count_3 % 3 == 0) {
   12307         110 :     CcTest::CollectAllGarbage();
   12308         110 :     GenerateSomeGarbage();
   12309             :   }
   12310         341 :   return v8_str("Direct Getter Result");
   12311             : }
   12312             : 
   12313             : 
   12314         341 : static void DirectGetterCallback(
   12315             :     Local<String> name,
   12316             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12317         341 :   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   12318         341 :   info.GetReturnValue().Set(DoDirectGetter());
   12319         341 : }
   12320             : 
   12321             : 
   12322             : template<typename Accessor>
   12323          11 : static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   12324          11 :   LocalContext context;
   12325          11 :   v8::Isolate* isolate = context->GetIsolate();
   12326          22 :   v8::HandleScope scope(isolate);
   12327          11 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12328          11 :   obj->SetAccessor(v8_str("p1"), accessor);
   12329          66 :   CHECK(context->Global()
   12330             :             ->Set(context.local(), v8_str("o1"),
   12331             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12332             :             .FromJust());
   12333          11 :   p_getter_count_3 = 0;
   12334             :   v8::Local<v8::Value> result = CompileRun(
   12335             :       "function f() {"
   12336             :       "  for (var i = 0; i < 30; i++) o1.p1;"
   12337             :       "  return o1.p1"
   12338             :       "}"
   12339          11 :       "f();");
   12340          33 :   CHECK(v8_str("Direct Getter Result")
   12341             :             ->Equals(context.local(), result)
   12342             :             .FromJust());
   12343          22 :   CHECK_EQ(31, p_getter_count_3);
   12344          11 : }
   12345             : 
   12346             : 
   12347       47452 : THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12348          11 :   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12349          11 : }
   12350             : 
   12351             : 
   12352          30 : void ThrowingDirectGetterCallback(
   12353             :     Local<String> name,
   12354             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12355          60 :   info.GetIsolate()->ThrowException(v8_str("g"));
   12356          30 : }
   12357             : 
   12358             : 
   12359       23724 : THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12360           6 :   LocalContext context;
   12361           6 :   v8::Isolate* isolate = context->GetIsolate();
   12362          12 :   v8::HandleScope scope(isolate);
   12363           6 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12364           6 :   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12365          36 :   CHECK(context->Global()
   12366             :             ->Set(context.local(), v8_str("o1"),
   12367             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12368             :             .FromJust());
   12369             :   v8::Local<Value> result = CompileRun(
   12370             :       "var result = '';"
   12371             :       "for (var i = 0; i < 5; i++) {"
   12372             :       "    try { o1.p1; } catch (e) { result += e; }"
   12373             :       "}"
   12374           6 :       "result;");
   12375          24 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12376           6 : }
   12377             : 
   12378             : 
   12379       47452 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12380          11 :   int interceptor_call_count = 0;
   12381          11 :   v8::Isolate* isolate = CcTest::isolate();
   12382          11 :   v8::HandleScope scope(isolate);
   12383             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12384          11 :       v8::FunctionTemplate::New(isolate);
   12385             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12386             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12387          22 :       v8::Local<v8::Signature>());
   12388          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12389          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12390          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12391             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12392             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12393          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12394          22 :   LocalContext context;
   12395             :   v8::Local<v8::Function> fun =
   12396          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12397          11 :   GenerateSomeGarbage();
   12398          66 :   CHECK(context->Global()
   12399             :             ->Set(context.local(), v8_str("o"),
   12400             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12401             :             .FromJust());
   12402             :   CompileRun(
   12403             :       "var result = 0;"
   12404             :       "for (var i = 0; i < 100; i++) {"
   12405             :       "  result = o.method(41);"
   12406             :       "}");
   12407          66 :   CHECK_EQ(42, context->Global()
   12408             :                    ->Get(context.local(), v8_str("result"))
   12409             :                    .ToLocalChecked()
   12410             :                    ->Int32Value(context.local())
   12411             :                    .FromJust());
   12412          22 :   CHECK_EQ(100, interceptor_call_count);
   12413          11 : }
   12414             : 
   12415             : 
   12416       47452 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   12417          11 :   int interceptor_call_count = 0;
   12418          11 :   v8::Isolate* isolate = CcTest::isolate();
   12419          11 :   v8::HandleScope scope(isolate);
   12420             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12421          11 :       v8::FunctionTemplate::New(isolate);
   12422             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12423             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12424          22 :       v8::Signature::New(isolate, fun_templ));
   12425          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12426          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12427          11 :   fun_templ->SetHiddenPrototype(true);
   12428          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12429             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12430             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12431          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12432          22 :   LocalContext context;
   12433             :   v8::Local<v8::Function> fun =
   12434          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12435          11 :   GenerateSomeGarbage();
   12436          66 :   CHECK(context->Global()
   12437             :             ->Set(context.local(), v8_str("o"),
   12438             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12439             :             .FromJust());
   12440             :   CompileRun(
   12441             :       "o.foo = 17;"
   12442             :       "var receiver = {};"
   12443             :       "receiver.__proto__ = o;"
   12444             :       "var result = 0;"
   12445             :       "for (var i = 0; i < 100; i++) {"
   12446             :       "  result = receiver.method(41);"
   12447             :       "}");
   12448          66 :   CHECK_EQ(42, context->Global()
   12449             :                    ->Get(context.local(), v8_str("result"))
   12450             :                    .ToLocalChecked()
   12451             :                    ->Int32Value(context.local())
   12452             :                    .FromJust());
   12453          22 :   CHECK_EQ(100, interceptor_call_count);
   12454          11 : }
   12455             : 
   12456             : 
   12457       47452 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   12458          11 :   int interceptor_call_count = 0;
   12459          11 :   v8::Isolate* isolate = CcTest::isolate();
   12460          11 :   v8::HandleScope scope(isolate);
   12461             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12462          11 :       v8::FunctionTemplate::New(isolate);
   12463             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12464             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12465          22 :       v8::Signature::New(isolate, fun_templ));
   12466          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12467          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12468          11 :   fun_templ->SetHiddenPrototype(true);
   12469          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12470             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12471             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12472          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12473          22 :   LocalContext context;
   12474             :   v8::Local<v8::Function> fun =
   12475          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12476          11 :   GenerateSomeGarbage();
   12477          66 :   CHECK(context->Global()
   12478             :             ->Set(context.local(), v8_str("o"),
   12479             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12480             :             .FromJust());
   12481             :   CompileRun(
   12482             :       "o.foo = 17;"
   12483             :       "var receiver = {};"
   12484             :       "receiver.__proto__ = o;"
   12485             :       "var result = 0;"
   12486             :       "var saved_result = 0;"
   12487             :       "for (var i = 0; i < 100; i++) {"
   12488             :       "  result = receiver.method(41);"
   12489             :       "  if (i == 50) {"
   12490             :       "    saved_result = result;"
   12491             :       "    receiver = {method: function(x) { return x - 1 }};"
   12492             :       "  }"
   12493             :       "}");
   12494          66 :   CHECK_EQ(40, context->Global()
   12495             :                    ->Get(context.local(), v8_str("result"))
   12496             :                    .ToLocalChecked()
   12497             :                    ->Int32Value(context.local())
   12498             :                    .FromJust());
   12499          66 :   CHECK_EQ(42, context->Global()
   12500             :                    ->Get(context.local(), v8_str("saved_result"))
   12501             :                    .ToLocalChecked()
   12502             :                    ->Int32Value(context.local())
   12503             :                    .FromJust());
   12504          22 :   CHECK_GE(interceptor_call_count, 50);
   12505          11 : }
   12506             : 
   12507             : 
   12508       47452 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   12509          11 :   int interceptor_call_count = 0;
   12510          11 :   v8::Isolate* isolate = CcTest::isolate();
   12511          11 :   v8::HandleScope scope(isolate);
   12512             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12513          11 :       v8::FunctionTemplate::New(isolate);
   12514             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12515             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12516          22 :       v8::Signature::New(isolate, fun_templ));
   12517          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12518          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12519          11 :   fun_templ->SetHiddenPrototype(true);
   12520          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12521             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12522             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12523          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12524          22 :   LocalContext context;
   12525             :   v8::Local<v8::Function> fun =
   12526          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12527          11 :   GenerateSomeGarbage();
   12528          66 :   CHECK(context->Global()
   12529             :             ->Set(context.local(), v8_str("o"),
   12530             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12531             :             .FromJust());
   12532             :   CompileRun(
   12533             :       "o.foo = 17;"
   12534             :       "var receiver = {};"
   12535             :       "receiver.__proto__ = o;"
   12536             :       "var result = 0;"
   12537             :       "var saved_result = 0;"
   12538             :       "for (var i = 0; i < 100; i++) {"
   12539             :       "  result = receiver.method(41);"
   12540             :       "  if (i == 50) {"
   12541             :       "    saved_result = result;"
   12542             :       "    o.method = function(x) { return x - 1 };"
   12543             :       "  }"
   12544             :       "}");
   12545          66 :   CHECK_EQ(40, context->Global()
   12546             :                    ->Get(context.local(), v8_str("result"))
   12547             :                    .ToLocalChecked()
   12548             :                    ->Int32Value(context.local())
   12549             :                    .FromJust());
   12550          66 :   CHECK_EQ(42, context->Global()
   12551             :                    ->Get(context.local(), v8_str("saved_result"))
   12552             :                    .ToLocalChecked()
   12553             :                    ->Int32Value(context.local())
   12554             :                    .FromJust());
   12555          22 :   CHECK_GE(interceptor_call_count, 50);
   12556          11 : }
   12557             : 
   12558             : 
   12559       47452 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   12560          11 :   int interceptor_call_count = 0;
   12561          11 :   v8::Isolate* isolate = CcTest::isolate();
   12562          11 :   v8::HandleScope scope(isolate);
   12563             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12564          11 :       v8::FunctionTemplate::New(isolate);
   12565             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12566             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12567          22 :       v8::Signature::New(isolate, fun_templ));
   12568          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12569          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12570          11 :   fun_templ->SetHiddenPrototype(true);
   12571          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12572             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12573             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12574          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12575          22 :   LocalContext context;
   12576             :   v8::Local<v8::Function> fun =
   12577          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12578          11 :   GenerateSomeGarbage();
   12579          66 :   CHECK(context->Global()
   12580             :             ->Set(context.local(), v8_str("o"),
   12581             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12582             :             .FromJust());
   12583          22 :   v8::TryCatch try_catch(isolate);
   12584             :   CompileRun(
   12585             :       "o.foo = 17;"
   12586             :       "var receiver = {};"
   12587             :       "receiver.__proto__ = o;"
   12588             :       "var result = 0;"
   12589             :       "var saved_result = 0;"
   12590             :       "for (var i = 0; i < 100; i++) {"
   12591             :       "  result = receiver.method(41);"
   12592             :       "  if (i == 50) {"
   12593             :       "    saved_result = result;"
   12594             :       "    receiver = 333;"
   12595             :       "  }"
   12596             :       "}");
   12597          11 :   CHECK(try_catch.HasCaught());
   12598             :   // TODO(verwaest): Adjust message.
   12599          55 :   CHECK(
   12600             :       v8_str("TypeError: receiver.method is not a function")
   12601             :           ->Equals(
   12602             :               context.local(),
   12603             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12604             :           .FromJust());
   12605          66 :   CHECK_EQ(42, context->Global()
   12606             :                    ->Get(context.local(), v8_str("saved_result"))
   12607             :                    .ToLocalChecked()
   12608             :                    ->Int32Value(context.local())
   12609             :                    .FromJust());
   12610          22 :   CHECK_GE(interceptor_call_count, 50);
   12611          11 : }
   12612             : 
   12613             : 
   12614       47452 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   12615          11 :   int interceptor_call_count = 0;
   12616          11 :   v8::Isolate* isolate = CcTest::isolate();
   12617          11 :   v8::HandleScope scope(isolate);
   12618             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12619          11 :       v8::FunctionTemplate::New(isolate);
   12620             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12621             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12622          22 :       v8::Signature::New(isolate, fun_templ));
   12623          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12624          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12625          11 :   fun_templ->SetHiddenPrototype(true);
   12626          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12627             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12628             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12629          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12630          22 :   LocalContext context;
   12631             :   v8::Local<v8::Function> fun =
   12632          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12633          11 :   GenerateSomeGarbage();
   12634          66 :   CHECK(context->Global()
   12635             :             ->Set(context.local(), v8_str("o"),
   12636             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12637             :             .FromJust());
   12638          22 :   v8::TryCatch try_catch(isolate);
   12639             :   CompileRun(
   12640             :       "o.foo = 17;"
   12641             :       "var receiver = {};"
   12642             :       "receiver.__proto__ = o;"
   12643             :       "var result = 0;"
   12644             :       "var saved_result = 0;"
   12645             :       "for (var i = 0; i < 100; i++) {"
   12646             :       "  result = receiver.method(41);"
   12647             :       "  if (i == 50) {"
   12648             :       "    saved_result = result;"
   12649             :       "    receiver = {method: receiver.method};"
   12650             :       "  }"
   12651             :       "}");
   12652          11 :   CHECK(try_catch.HasCaught());
   12653          55 :   CHECK(
   12654             :       v8_str("TypeError: Illegal invocation")
   12655             :           ->Equals(
   12656             :               context.local(),
   12657             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12658             :           .FromJust());
   12659          66 :   CHECK_EQ(42, context->Global()
   12660             :                    ->Get(context.local(), v8_str("saved_result"))
   12661             :                    .ToLocalChecked()
   12662             :                    ->Int32Value(context.local())
   12663             :                    .FromJust());
   12664          22 :   CHECK_GE(interceptor_call_count, 50);
   12665          11 : }
   12666             : 
   12667             : 
   12668       47452 : THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12669          11 :   v8::Isolate* isolate = CcTest::isolate();
   12670          11 :   v8::HandleScope scope(isolate);
   12671             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12672          11 :       v8::FunctionTemplate::New(isolate);
   12673             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12674             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12675          22 :       v8::Local<v8::Signature>());
   12676          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12677          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12678          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12679             :   USE(templ);
   12680          22 :   LocalContext context;
   12681             :   v8::Local<v8::Function> fun =
   12682          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12683          11 :   GenerateSomeGarbage();
   12684          66 :   CHECK(context->Global()
   12685             :             ->Set(context.local(), v8_str("o"),
   12686             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12687             :             .FromJust());
   12688             :   CompileRun(
   12689             :       "var result = 0;"
   12690             :       "for (var i = 0; i < 100; i++) {"
   12691             :       "  result = o.method(41);"
   12692             :       "}");
   12693             : 
   12694          66 :   CHECK_EQ(42, context->Global()
   12695             :                    ->Get(context.local(), v8_str("result"))
   12696             :                    .ToLocalChecked()
   12697             :                    ->Int32Value(context.local())
   12698          11 :                    .FromJust());
   12699          11 : }
   12700             : 
   12701             : 
   12702       47452 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   12703          11 :   v8::Isolate* isolate = CcTest::isolate();
   12704          11 :   v8::HandleScope scope(isolate);
   12705             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12706          11 :       v8::FunctionTemplate::New(isolate);
   12707             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12708             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12709          22 :       v8::Signature::New(isolate, fun_templ));
   12710          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12711          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12712          11 :   fun_templ->SetHiddenPrototype(true);
   12713          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12714          11 :   CHECK(!templ.IsEmpty());
   12715          22 :   LocalContext context;
   12716             :   v8::Local<v8::Function> fun =
   12717          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12718          11 :   GenerateSomeGarbage();
   12719          66 :   CHECK(context->Global()
   12720             :             ->Set(context.local(), v8_str("o"),
   12721             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12722             :             .FromJust());
   12723             :   CompileRun(
   12724             :       "o.foo = 17;"
   12725             :       "var receiver = {};"
   12726             :       "receiver.__proto__ = o;"
   12727             :       "var result = 0;"
   12728             :       "for (var i = 0; i < 100; i++) {"
   12729             :       "  result = receiver.method(41);"
   12730             :       "}");
   12731             : 
   12732          66 :   CHECK_EQ(42, context->Global()
   12733             :                    ->Get(context.local(), v8_str("result"))
   12734             :                    .ToLocalChecked()
   12735             :                    ->Int32Value(context.local())
   12736          11 :                    .FromJust());
   12737          11 : }
   12738             : 
   12739             : 
   12740       47452 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   12741          11 :   v8::Isolate* isolate = CcTest::isolate();
   12742          11 :   v8::HandleScope scope(isolate);
   12743             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12744          11 :       v8::FunctionTemplate::New(isolate);
   12745             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12746             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12747          22 :       v8::Signature::New(isolate, fun_templ));
   12748          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12749          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12750          11 :   fun_templ->SetHiddenPrototype(true);
   12751          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12752          11 :   CHECK(!templ.IsEmpty());
   12753          22 :   LocalContext context;
   12754             :   v8::Local<v8::Function> fun =
   12755          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12756          11 :   GenerateSomeGarbage();
   12757          66 :   CHECK(context->Global()
   12758             :             ->Set(context.local(), v8_str("o"),
   12759             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12760             :             .FromJust());
   12761             :   CompileRun(
   12762             :       "o.foo = 17;"
   12763             :       "var receiver = {};"
   12764             :       "receiver.__proto__ = o;"
   12765             :       "var result = 0;"
   12766             :       "var saved_result = 0;"
   12767             :       "for (var i = 0; i < 100; i++) {"
   12768             :       "  result = receiver.method(41);"
   12769             :       "  if (i == 50) {"
   12770             :       "    saved_result = result;"
   12771             :       "    receiver = {method: function(x) { return x - 1 }};"
   12772             :       "  }"
   12773             :       "}");
   12774          66 :   CHECK_EQ(40, context->Global()
   12775             :                    ->Get(context.local(), v8_str("result"))
   12776             :                    .ToLocalChecked()
   12777             :                    ->Int32Value(context.local())
   12778             :                    .FromJust());
   12779          66 :   CHECK_EQ(42, context->Global()
   12780             :                    ->Get(context.local(), v8_str("saved_result"))
   12781             :                    .ToLocalChecked()
   12782             :                    ->Int32Value(context.local())
   12783          11 :                    .FromJust());
   12784          11 : }
   12785             : 
   12786             : 
   12787       47452 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   12788          11 :   v8::Isolate* isolate = CcTest::isolate();
   12789          11 :   v8::HandleScope scope(isolate);
   12790             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12791          11 :       v8::FunctionTemplate::New(isolate);
   12792             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12793             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12794          22 :       v8::Signature::New(isolate, fun_templ));
   12795          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12796          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12797          11 :   fun_templ->SetHiddenPrototype(true);
   12798          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12799          11 :   CHECK(!templ.IsEmpty());
   12800          22 :   LocalContext context;
   12801             :   v8::Local<v8::Function> fun =
   12802          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12803          11 :   GenerateSomeGarbage();
   12804          66 :   CHECK(context->Global()
   12805             :             ->Set(context.local(), v8_str("o"),
   12806             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12807             :             .FromJust());
   12808          22 :   v8::TryCatch try_catch(isolate);
   12809             :   CompileRun(
   12810             :       "o.foo = 17;"
   12811             :       "var receiver = {};"
   12812             :       "receiver.__proto__ = o;"
   12813             :       "var result = 0;"
   12814             :       "var saved_result = 0;"
   12815             :       "for (var i = 0; i < 100; i++) {"
   12816             :       "  result = receiver.method(41);"
   12817             :       "  if (i == 50) {"
   12818             :       "    saved_result = result;"
   12819             :       "    receiver = 333;"
   12820             :       "  }"
   12821             :       "}");
   12822          11 :   CHECK(try_catch.HasCaught());
   12823             :   // TODO(verwaest): Adjust message.
   12824          55 :   CHECK(
   12825             :       v8_str("TypeError: receiver.method is not a function")
   12826             :           ->Equals(
   12827             :               context.local(),
   12828             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12829             :           .FromJust());
   12830          66 :   CHECK_EQ(42, context->Global()
   12831             :                    ->Get(context.local(), v8_str("saved_result"))
   12832             :                    .ToLocalChecked()
   12833             :                    ->Int32Value(context.local())
   12834          11 :                    .FromJust());
   12835          11 : }
   12836             : 
   12837             : 
   12838       47452 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   12839          11 :   v8::Isolate* isolate = CcTest::isolate();
   12840          11 :   v8::HandleScope scope(isolate);
   12841             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12842          11 :       v8::FunctionTemplate::New(isolate);
   12843             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12844             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12845          22 :       v8::Signature::New(isolate, fun_templ));
   12846          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12847          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12848          11 :   fun_templ->SetHiddenPrototype(true);
   12849          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12850          11 :   CHECK(!templ.IsEmpty());
   12851          22 :   LocalContext context;
   12852             :   v8::Local<v8::Function> fun =
   12853          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12854          11 :   GenerateSomeGarbage();
   12855          66 :   CHECK(context->Global()
   12856             :             ->Set(context.local(), v8_str("o"),
   12857             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12858             :             .FromJust());
   12859          22 :   v8::TryCatch try_catch(isolate);
   12860             :   CompileRun(
   12861             :       "o.foo = 17;"
   12862             :       "var receiver = {};"
   12863             :       "receiver.__proto__ = o;"
   12864             :       "var result = 0;"
   12865             :       "var saved_result = 0;"
   12866             :       "for (var i = 0; i < 100; i++) {"
   12867             :       "  result = receiver.method(41);"
   12868             :       "  if (i == 50) {"
   12869             :       "    saved_result = result;"
   12870             :       "    receiver = Object.create(receiver);"
   12871             :       "  }"
   12872             :       "}");
   12873          11 :   CHECK(try_catch.HasCaught());
   12874          55 :   CHECK(
   12875             :       v8_str("TypeError: Illegal invocation")
   12876             :           ->Equals(
   12877             :               context.local(),
   12878             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12879             :           .FromJust());
   12880          66 :   CHECK_EQ(42, context->Global()
   12881             :                    ->Get(context.local(), v8_str("saved_result"))
   12882             :                    .ToLocalChecked()
   12883             :                    ->Int32Value(context.local())
   12884          11 :                    .FromJust());
   12885          11 : }
   12886             : 
   12887             : 
   12888          24 : static void ThrowingGetter(Local<String> name,
   12889             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12890          24 :   ApiTestFuzzer::Fuzz();
   12891          24 :   info.GetIsolate()->ThrowException(Local<Value>());
   12892             :   info.GetReturnValue().SetUndefined();
   12893          24 : }
   12894             : 
   12895             : 
   12896       23724 : THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12897           6 :   LocalContext context;
   12898          12 :   HandleScope scope(context->GetIsolate());
   12899             : 
   12900           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   12901           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12902          12 :   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12903             : 
   12904           6 :   Local<Object> instance = templ->GetFunction(context.local())
   12905           6 :                                .ToLocalChecked()
   12906           6 :                                ->NewInstance(context.local())
   12907             :                                .ToLocalChecked();
   12908             : 
   12909           6 :   Local<Object> another = Object::New(context->GetIsolate());
   12910          12 :   CHECK(another->SetPrototype(context.local(), instance).FromJust());
   12911             : 
   12912             :   Local<Object> with_js_getter = CompileRun(
   12913             :       "o = {};\n"
   12914             :       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12915             :       "o\n").As<Object>();
   12916           6 :   CHECK(!with_js_getter.IsEmpty());
   12917             : 
   12918          12 :   TryCatch try_catch(context->GetIsolate());
   12919             : 
   12920             :   v8::MaybeLocal<Value> result =
   12921          12 :       instance->GetRealNamedProperty(context.local(), v8_str("f"));
   12922           6 :   CHECK(try_catch.HasCaught());
   12923           6 :   try_catch.Reset();
   12924           6 :   CHECK(result.IsEmpty());
   12925             : 
   12926             :   Maybe<PropertyAttribute> attr =
   12927          12 :       instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12928           6 :   CHECK(!try_catch.HasCaught());
   12929           6 :   CHECK(Just(None) == attr);
   12930             : 
   12931          12 :   result = another->GetRealNamedProperty(context.local(), v8_str("f"));
   12932           6 :   CHECK(try_catch.HasCaught());
   12933           6 :   try_catch.Reset();
   12934           6 :   CHECK(result.IsEmpty());
   12935             : 
   12936          12 :   attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12937           6 :   CHECK(!try_catch.HasCaught());
   12938           6 :   CHECK(Just(None) == attr);
   12939             : 
   12940             :   result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
   12941          12 :                                                          v8_str("f"));
   12942           6 :   CHECK(try_catch.HasCaught());
   12943           6 :   try_catch.Reset();
   12944           6 :   CHECK(result.IsEmpty());
   12945             : 
   12946             :   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
   12947          12 :       context.local(), v8_str("f"));
   12948           6 :   CHECK(!try_catch.HasCaught());
   12949           6 :   CHECK(Just(None) == attr);
   12950             : 
   12951          12 :   result = another->Get(context.local(), v8_str("f"));
   12952           6 :   CHECK(try_catch.HasCaught());
   12953           6 :   try_catch.Reset();
   12954           6 :   CHECK(result.IsEmpty());
   12955             : 
   12956          12 :   result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
   12957           6 :   CHECK(try_catch.HasCaught());
   12958           6 :   try_catch.Reset();
   12959           6 :   CHECK(result.IsEmpty());
   12960             : 
   12961             :   attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
   12962          12 :                                                         v8_str("f"));
   12963           6 :   CHECK(!try_catch.HasCaught());
   12964           6 :   CHECK(Just(None) == attr);
   12965             : 
   12966          12 :   result = with_js_getter->Get(context.local(), v8_str("f"));
   12967           6 :   CHECK(try_catch.HasCaught());
   12968           6 :   try_catch.Reset();
   12969           6 :   CHECK(result.IsEmpty());
   12970             : 
   12971             :   Local<Object> target = CompileRun("({})").As<Object>();
   12972           6 :   Local<Object> handler = CompileRun("({})").As<Object>();
   12973             :   Local<v8::Proxy> proxy =
   12974           6 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   12975             : 
   12976          12 :   result = target->GetRealNamedProperty(context.local(), v8_str("f"));
   12977           6 :   CHECK(!try_catch.HasCaught());
   12978           6 :   CHECK(result.IsEmpty());
   12979             : 
   12980          12 :   result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
   12981           6 :   CHECK(!try_catch.HasCaught());
   12982          12 :   CHECK(result.IsEmpty());
   12983           6 : }
   12984             : 
   12985             : 
   12986          30 : static void ThrowingCallbackWithTryCatch(
   12987          30 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12988          30 :   TryCatch try_catch(args.GetIsolate());
   12989             :   // Verboseness is important: it triggers message delivery which can call into
   12990             :   // external code.
   12991          30 :   try_catch.SetVerbose(true);
   12992             :   CompileRun("throw 'from JS';");
   12993          30 :   CHECK(try_catch.HasCaught());
   12994          30 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   12995          30 :   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   12996          30 : }
   12997             : 
   12998             : 
   12999             : static int call_depth;
   13000             : 
   13001             : 
   13002           6 : static void WithTryCatch(Local<Message> message, Local<Value> data) {
   13003           6 :   TryCatch try_catch(CcTest::isolate());
   13004           6 : }
   13005             : 
   13006             : 
   13007           6 : static void ThrowFromJS(Local<Message> message, Local<Value> data) {
   13008           6 :   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   13009           6 : }
   13010             : 
   13011             : 
   13012           6 : static void ThrowViaApi(Local<Message> message, Local<Value> data) {
   13013          12 :   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   13014           6 : }
   13015             : 
   13016             : 
   13017           6 : static void WebKitLike(Local<Message> message, Local<Value> data) {
   13018           6 :   Local<String> errorMessageString = message->Get();
   13019           6 :   CHECK(!errorMessageString.IsEmpty());
   13020           6 :   message->GetStackTrace();
   13021           6 :   message->GetScriptOrigin().ResourceName();
   13022           6 : }
   13023             : 
   13024             : 
   13025       23724 : THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   13026           6 :   LocalContext context;
   13027           6 :   v8::Isolate* isolate = context->GetIsolate();
   13028          12 :   HandleScope scope(isolate);
   13029             : 
   13030             :   Local<Function> func =
   13031           6 :       FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
   13032          18 :           ->GetFunction(context.local())
   13033           6 :           .ToLocalChecked();
   13034          30 :   CHECK(
   13035             :       context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
   13036             : 
   13037             :   MessageCallback callbacks[] = {nullptr, WebKitLike, ThrowViaApi, ThrowFromJS,
   13038           6 :                                  WithTryCatch};
   13039          36 :   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   13040          30 :     MessageCallback callback = callbacks[i];
   13041          30 :     if (callback != nullptr) {
   13042          24 :       isolate->AddMessageListener(callback);
   13043             :     }
   13044             :     // Some small number to control number of times message handler should
   13045             :     // throw an exception.
   13046          30 :     call_depth = 5;
   13047             :     ExpectFalse(
   13048             :         "var thrown = false;\n"
   13049             :         "try { func(); } catch(e) { thrown = true; }\n"
   13050             :         "thrown\n");
   13051          30 :     if (callback != nullptr) {
   13052          24 :       isolate->RemoveMessageListeners(callback);
   13053             :     }
   13054           6 :   }
   13055           6 : }
   13056             : 
   13057             : 
   13058           6 : static void ParentGetter(Local<String> name,
   13059             :                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   13060           6 :   ApiTestFuzzer::Fuzz();
   13061           6 :   info.GetReturnValue().Set(v8_num(1));
   13062           6 : }
   13063             : 
   13064             : 
   13065          18 : static void ChildGetter(Local<String> name,
   13066             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   13067          18 :   ApiTestFuzzer::Fuzz();
   13068          18 :   info.GetReturnValue().Set(v8_num(42));
   13069          18 : }
   13070             : 
   13071             : 
   13072       23724 : THREADED_TEST(Overriding) {
   13073           6 :   LocalContext context;
   13074           6 :   v8::Isolate* isolate = context->GetIsolate();
   13075          12 :   v8::HandleScope scope(isolate);
   13076             : 
   13077             :   // Parent template.
   13078           6 :   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   13079             :   Local<ObjectTemplate> parent_instance_templ =
   13080           6 :       parent_templ->InstanceTemplate();
   13081          12 :   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   13082             : 
   13083             :   // Template that inherits from the parent template.
   13084           6 :   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   13085             :   Local<ObjectTemplate> child_instance_templ =
   13086           6 :       child_templ->InstanceTemplate();
   13087           6 :   child_templ->Inherit(parent_templ);
   13088             :   // Override 'f'.  The child version of 'f' should get called for child
   13089             :   // instances.
   13090           6 :   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   13091             :   // Add 'g' twice.  The 'g' added last should get called for instances.
   13092           6 :   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   13093           6 :   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   13094             : 
   13095             :   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   13096             :   // so 'h' can be shadowed on the instance object.
   13097           6 :   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   13098             :   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
   13099          12 :                                  v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
   13100             : 
   13101             :   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   13102             :   // but the attribute does not have effect because it is duplicated with
   13103             :   // nullptr setter.
   13104             :   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
   13105             :                                     v8::Local<Value>(), v8::DEFAULT,
   13106           6 :                                     v8::ReadOnly);
   13107             : 
   13108             : 
   13109             :   // Instantiate the child template.
   13110           6 :   Local<v8::Object> instance = child_templ->GetFunction(context.local())
   13111           6 :                                    .ToLocalChecked()
   13112           6 :                                    ->NewInstance(context.local())
   13113             :                                    .ToLocalChecked();
   13114             : 
   13115             :   // Check that the child function overrides the parent one.
   13116          30 :   CHECK(context->Global()
   13117             :             ->Set(context.local(), v8_str("o"), instance)
   13118             :             .FromJust());
   13119          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13120             :   // Check that the 'g' that was added last is hit.
   13121          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13122          12 :   value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
   13123          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13124             : 
   13125             :   // Check that 'h' cannot be shadowed.
   13126          12 :   value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
   13127          12 :   CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
   13128             : 
   13129             :   // Check that 'i' cannot be shadowed or changed.
   13130          12 :   value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
   13131          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13132           6 : }
   13133             : 
   13134             : 
   13135          24 : static void ShouldThrowOnErrorGetter(
   13136             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   13137          24 :   ApiTestFuzzer::Fuzz();
   13138             :   v8::Isolate* isolate = info.GetIsolate();
   13139             :   Local<Boolean> should_throw_on_error =
   13140             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13141             :   info.GetReturnValue().Set(should_throw_on_error);
   13142          24 : }
   13143             : 
   13144             : 
   13145             : template <typename T>
   13146          24 : static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
   13147             :                                      const v8::PropertyCallbackInfo<T>& info) {
   13148          24 :   ApiTestFuzzer::Fuzz();
   13149             :   v8::Isolate* isolate = info.GetIsolate();
   13150          24 :   auto context = isolate->GetCurrentContext();
   13151             :   Local<Boolean> should_throw_on_error_value =
   13152             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13153         120 :   CHECK(context->Global()
   13154             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
   13155             :                   should_throw_on_error_value)
   13156             :             .FromJust());
   13157          24 : }
   13158             : 
   13159             : 
   13160       23724 : THREADED_TEST(AccessorShouldThrowOnError) {
   13161           6 :   LocalContext context;
   13162           6 :   v8::Isolate* isolate = context->GetIsolate();
   13163          12 :   v8::HandleScope scope(isolate);
   13164           6 :   Local<Object> global = context->Global();
   13165             : 
   13166           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13167           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   13168             :   instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
   13169          12 :                               ShouldThrowOnErrorSetter<void>);
   13170             : 
   13171           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13172           6 :                                    .ToLocalChecked()
   13173           6 :                                    ->NewInstance(context.local())
   13174             :                                    .ToLocalChecked();
   13175             : 
   13176          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   13177             : 
   13178             :   // SLOPPY mode
   13179          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13180           6 :   CHECK(value->IsFalse());
   13181          12 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   13182          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13183           6 :               .ToLocalChecked();
   13184           6 :   CHECK(value->IsFalse());
   13185             : 
   13186             :   // STRICT mode
   13187          12 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   13188           6 :   CHECK(value->IsFalse());
   13189          12 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   13190          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13191           6 :               .ToLocalChecked();
   13192          12 :   CHECK(value->IsTrue());
   13193           6 : }
   13194             : 
   13195             : 
   13196           0 : static void ShouldThrowOnErrorQuery(
   13197             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   13198           0 :   ApiTestFuzzer::Fuzz();
   13199             :   v8::Isolate* isolate = info.GetIsolate();
   13200             :   info.GetReturnValue().Set(v8::None);
   13201             : 
   13202           0 :   auto context = isolate->GetCurrentContext();
   13203             :   Local<Boolean> should_throw_on_error_value =
   13204             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13205           0 :   CHECK(context->Global()
   13206             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
   13207             :                   should_throw_on_error_value)
   13208             :             .FromJust());
   13209           0 : }
   13210             : 
   13211             : 
   13212          12 : static void ShouldThrowOnErrorDeleter(
   13213             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   13214          12 :   ApiTestFuzzer::Fuzz();
   13215             :   v8::Isolate* isolate = info.GetIsolate();
   13216             :   info.GetReturnValue().Set(v8::True(isolate));
   13217             : 
   13218          12 :   auto context = isolate->GetCurrentContext();
   13219             :   Local<Boolean> should_throw_on_error_value =
   13220             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13221          60 :   CHECK(context->Global()
   13222             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
   13223             :                   should_throw_on_error_value)
   13224             :             .FromJust());
   13225          12 : }
   13226             : 
   13227             : 
   13228          12 : static void ShouldThrowOnErrorPropertyEnumerator(
   13229             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
   13230          12 :   ApiTestFuzzer::Fuzz();
   13231             :   v8::Isolate* isolate = info.GetIsolate();
   13232          12 :   Local<v8::Array> names = v8::Array::New(isolate, 1);
   13233          36 :   CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
   13234             :   info.GetReturnValue().Set(names);
   13235             : 
   13236          12 :   auto context = isolate->GetCurrentContext();
   13237             :   Local<Boolean> should_throw_on_error_value =
   13238             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13239          60 :   CHECK(context->Global()
   13240             :             ->Set(isolate->GetCurrentContext(),
   13241             :                   v8_str("should_throw_enumerator"),
   13242             :                   should_throw_on_error_value)
   13243             :             .FromJust());
   13244          12 : }
   13245             : 
   13246             : 
   13247       23724 : THREADED_TEST(InterceptorShouldThrowOnError) {
   13248           6 :   LocalContext context;
   13249           6 :   v8::Isolate* isolate = context->GetIsolate();
   13250          12 :   v8::HandleScope scope(isolate);
   13251           6 :   Local<Object> global = context->Global();
   13252             : 
   13253           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
   13254             :   v8::NamedPropertyHandlerConfiguration handler(
   13255             :       ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
   13256             :       ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
   13257             :       ShouldThrowOnErrorPropertyEnumerator);
   13258           6 :   interceptor_templ->SetHandler(handler);
   13259             : 
   13260             :   Local<v8::Object> instance =
   13261           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
   13262             : 
   13263          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   13264             : 
   13265             :   // SLOPPY mode
   13266          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13267           6 :   CHECK(value->IsFalse());
   13268          12 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   13269          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13270           6 :               .ToLocalChecked();
   13271           6 :   CHECK(value->IsFalse());
   13272             : 
   13273          12 :   v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
   13274          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   13275           6 :               .ToLocalChecked();
   13276           6 :   CHECK(value->IsFalse());
   13277             : 
   13278             :   v8_compile("Object.getOwnPropertyNames(o)")
   13279           6 :       ->Run(context.local())
   13280           6 :       .ToLocalChecked();
   13281          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   13282           6 :               .ToLocalChecked();
   13283           6 :   CHECK(value->IsFalse());
   13284             : 
   13285             :   // STRICT mode
   13286          12 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   13287           6 :   CHECK(value->IsFalse());
   13288          12 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   13289          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13290           6 :               .ToLocalChecked();
   13291           6 :   CHECK(value->IsTrue());
   13292             : 
   13293          12 :   v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
   13294          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   13295           6 :               .ToLocalChecked();
   13296           6 :   CHECK(value->IsTrue());
   13297             : 
   13298             :   v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
   13299           6 :       ->Run(context.local())
   13300           6 :       .ToLocalChecked();
   13301          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   13302           6 :               .ToLocalChecked();
   13303          12 :   CHECK(value->IsFalse());
   13304           6 : }
   13305             : 
   13306             : 
   13307          12 : static void IsConstructHandler(
   13308             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13309          12 :   ApiTestFuzzer::Fuzz();
   13310             :   args.GetReturnValue().Set(args.IsConstructCall());
   13311          12 : }
   13312             : 
   13313             : 
   13314       23724 : THREADED_TEST(IsConstructCall) {
   13315           6 :   v8::Isolate* isolate = CcTest::isolate();
   13316           6 :   v8::HandleScope scope(isolate);
   13317             : 
   13318             :   // Function template with call handler.
   13319           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13320           6 :   templ->SetCallHandler(IsConstructHandler);
   13321             : 
   13322          12 :   LocalContext context;
   13323             : 
   13324          36 :   CHECK(context->Global()
   13325             :             ->Set(context.local(), v8_str("f"),
   13326             :                   templ->GetFunction(context.local()).ToLocalChecked())
   13327             :             .FromJust());
   13328          12 :   Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
   13329          12 :   CHECK(!value->BooleanValue(context.local()).FromJust());
   13330          12 :   value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
   13331          18 :   CHECK(value->BooleanValue(context.local()).FromJust());
   13332           6 : }
   13333             : 
   13334          48 : static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13335          24 :   ApiTestFuzzer::Fuzz();
   13336             :   args.GetReturnValue().Set(args.NewTarget());
   13337          24 : }
   13338             : 
   13339       23724 : THREADED_TEST(NewTargetHandler) {
   13340           6 :   v8::Isolate* isolate = CcTest::isolate();
   13341           6 :   v8::HandleScope scope(isolate);
   13342             : 
   13343             :   // Function template with call handler.
   13344           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13345           6 :   templ->SetCallHandler(NewTargetHandler);
   13346             : 
   13347          12 :   LocalContext context;
   13348             : 
   13349             :   Local<Function> function =
   13350           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   13351          30 :   CHECK(context->Global()
   13352             :             ->Set(context.local(), v8_str("f"), function)
   13353             :             .FromJust());
   13354             :   Local<Value> value = CompileRun("f()");
   13355           6 :   CHECK(value->IsUndefined());
   13356             :   value = CompileRun("new f()");
   13357           6 :   CHECK(value->IsFunction());
   13358           6 :   CHECK(value == function);
   13359             :   Local<Value> subclass = CompileRun("var g = class extends f { }; g");
   13360           6 :   CHECK(subclass->IsFunction());
   13361             :   value = CompileRun("new g()");
   13362           6 :   CHECK(value->IsFunction());
   13363           6 :   CHECK(value == subclass);
   13364             :   value = CompileRun("Reflect.construct(f, [], Array)");
   13365           6 :   CHECK(value->IsFunction());
   13366          30 :   CHECK(value ==
   13367             :         context->Global()
   13368             :             ->Get(context.local(), v8_str("Array"))
   13369           6 :             .ToLocalChecked());
   13370           6 : }
   13371             : 
   13372       23724 : THREADED_TEST(ObjectProtoToString) {
   13373           6 :   v8::Isolate* isolate = CcTest::isolate();
   13374           6 :   v8::HandleScope scope(isolate);
   13375           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13376           6 :   templ->SetClassName(v8_str("MyClass"));
   13377             : 
   13378          12 :   LocalContext context;
   13379             : 
   13380           6 :   Local<String> customized_tostring = v8_str("customized toString");
   13381             : 
   13382             :   // Replace Object.prototype.toString
   13383             :   v8_compile(
   13384             :       "Object.prototype.toString = function() {"
   13385             :       "  return 'customized toString';"
   13386             :       "}")
   13387           6 :       ->Run(context.local())
   13388           6 :       .ToLocalChecked();
   13389             : 
   13390             :   // Normal ToString call should call replaced Object.prototype.toString
   13391           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13392           6 :                                    .ToLocalChecked()
   13393           6 :                                    ->NewInstance(context.local())
   13394             :                                    .ToLocalChecked();
   13395           6 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13396          18 :   CHECK(value->IsString() &&
   13397             :         value->Equals(context.local(), customized_tostring).FromJust());
   13398             : 
   13399             :   // ObjectProtoToString should not call replace toString function.
   13400           6 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13401          18 :   CHECK(value->IsString() &&
   13402             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13403             : 
   13404             :   // Check global
   13405             :   value =
   13406          24 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13407          18 :   CHECK(value->IsString() &&
   13408             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13409             : 
   13410             :   // Check ordinary object
   13411             :   Local<Value> object =
   13412          12 :       v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
   13413             :   value = object.As<v8::Object>()
   13414           6 :               ->ObjectProtoToString(context.local())
   13415           6 :               .ToLocalChecked();
   13416          18 :   CHECK(value->IsString() &&
   13417           6 :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13418           6 : }
   13419             : 
   13420             : 
   13421       23723 : TEST(ObjectProtoToStringES6) {
   13422           5 :   LocalContext context;
   13423           5 :   v8::Isolate* isolate = CcTest::isolate();
   13424          10 :   v8::HandleScope scope(isolate);
   13425           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13426           5 :   templ->SetClassName(v8_str("MyClass"));
   13427             : 
   13428           5 :   Local<String> customized_tostring = v8_str("customized toString");
   13429             : 
   13430             :   // Replace Object.prototype.toString
   13431             :   CompileRun(
   13432             :       "Object.prototype.toString = function() {"
   13433             :       "  return 'customized toString';"
   13434             :       "}");
   13435             : 
   13436             :   // Normal ToString call should call replaced Object.prototype.toString
   13437           5 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13438           5 :                                    .ToLocalChecked()
   13439           5 :                                    ->NewInstance(context.local())
   13440             :                                    .ToLocalChecked();
   13441           5 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13442          15 :   CHECK(value->IsString() &&
   13443             :         value->Equals(context.local(), customized_tostring).FromJust());
   13444             : 
   13445             :   // ObjectProtoToString should not call replace toString function.
   13446           5 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13447          15 :   CHECK(value->IsString() &&
   13448             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13449             : 
   13450             :   // Check global
   13451             :   value =
   13452          20 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13453          15 :   CHECK(value->IsString() &&
   13454             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13455             : 
   13456             :   // Check ordinary object
   13457             :   Local<Value> object = CompileRun("new Object()");
   13458             :   value = object.As<v8::Object>()
   13459           5 :               ->ObjectProtoToString(context.local())
   13460           5 :               .ToLocalChecked();
   13461          15 :   CHECK(value->IsString() &&
   13462             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13463             : 
   13464             :   // Check that ES6 semantics using @@toStringTag work
   13465           5 :   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
   13466             : 
   13467             : #define TEST_TOSTRINGTAG(type, tag, expected)                              \
   13468             :   do {                                                                     \
   13469             :     object = CompileRun("new " #type "()");                                \
   13470             :     CHECK(object.As<v8::Object>()                                          \
   13471             :               ->Set(context.local(), toStringTag, v8_str(#tag))            \
   13472             :               .FromJust());                                                \
   13473             :     value = object.As<v8::Object>()                                        \
   13474             :                 ->ObjectProtoToString(context.local())                     \
   13475             :                 .ToLocalChecked();                                         \
   13476             :     CHECK(value->IsString() &&                                             \
   13477             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13478             :               .FromJust());                                                \
   13479             :   } while (0)
   13480             : 
   13481          30 :   TEST_TOSTRINGTAG(Array, Object, Object);
   13482          30 :   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
   13483          30 :   TEST_TOSTRINGTAG(Object, Array, Array);
   13484          30 :   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
   13485          30 :   TEST_TOSTRINGTAG(Object, Date, Date);
   13486          30 :   TEST_TOSTRINGTAG(Object, Error, Error);
   13487          30 :   TEST_TOSTRINGTAG(Object, Function, Function);
   13488          30 :   TEST_TOSTRINGTAG(Object, Number, Number);
   13489          30 :   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
   13490          30 :   TEST_TOSTRINGTAG(Object, String, String);
   13491          30 :   TEST_TOSTRINGTAG(Object, Foo, Foo);
   13492             : 
   13493             : #undef TEST_TOSTRINGTAG
   13494             : 
   13495             :   Local<v8::RegExp> valueRegExp =
   13496           5 :       v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
   13497           5 :           .ToLocalChecked();
   13498           5 :   Local<Value> valueNumber = v8_num(123);
   13499           5 :   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
   13500             :   Local<v8::Function> valueFunction =
   13501             :       CompileRun("(function fn() {})").As<v8::Function>();
   13502           5 :   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
   13503           5 :   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
   13504           5 :   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
   13505             : 
   13506             : #define TEST_TOSTRINGTAG(type, tagValue, expected)                         \
   13507             :   do {                                                                     \
   13508             :     object = CompileRun("new " #type "()");                                \
   13509             :     CHECK(object.As<v8::Object>()                                          \
   13510             :               ->Set(context.local(), toStringTag, tagValue)                \
   13511             :               .FromJust());                                                \
   13512             :     value = object.As<v8::Object>()                                        \
   13513             :                 ->ObjectProtoToString(context.local())                     \
   13514             :                 .ToLocalChecked();                                         \
   13515             :     CHECK(value->IsString() &&                                             \
   13516             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13517             :               .FromJust());                                                \
   13518             :   } while (0)
   13519             : 
   13520             : #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
   13521             :   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
   13522             :   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
   13523             :   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
   13524             :   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
   13525             :   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
   13526             :   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
   13527             : 
   13528             :   // Test non-String-valued @@toStringTag
   13529         150 :   TEST_TOSTRINGTAG_TYPES(valueRegExp);
   13530         150 :   TEST_TOSTRINGTAG_TYPES(valueNumber);
   13531         150 :   TEST_TOSTRINGTAG_TYPES(valueSymbol);
   13532         150 :   TEST_TOSTRINGTAG_TYPES(valueFunction);
   13533         150 :   TEST_TOSTRINGTAG_TYPES(valueObject);
   13534         150 :   TEST_TOSTRINGTAG_TYPES(valueNull);
   13535         150 :   TEST_TOSTRINGTAG_TYPES(valueUndef);
   13536             : 
   13537             : #undef TEST_TOSTRINGTAG
   13538             : #undef TEST_TOSTRINGTAG_TYPES
   13539             : 
   13540             :   // @@toStringTag getter throws
   13541           5 :   Local<Value> obj = v8::Object::New(isolate);
   13542             :   obj.As<v8::Object>()
   13543          10 :       ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
   13544          10 :       .FromJust();
   13545             :   {
   13546           5 :     TryCatch try_catch(isolate);
   13547          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13548           5 :     CHECK(try_catch.HasCaught());
   13549             :   }
   13550             : 
   13551             :   // @@toStringTag getter does not throw
   13552           5 :   obj = v8::Object::New(isolate);
   13553             :   obj.As<v8::Object>()
   13554             :       ->SetAccessor(context.local(), toStringTag,
   13555          15 :                     SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
   13556          10 :       .FromJust();
   13557             :   {
   13558           5 :     TryCatch try_catch(isolate);
   13559             :     value = obj.As<v8::Object>()
   13560           5 :                 ->ObjectProtoToString(context.local())
   13561           5 :                 .ToLocalChecked();
   13562          15 :     CHECK(value->IsString() &&
   13563             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13564           5 :     CHECK(!try_catch.HasCaught());
   13565             :   }
   13566             : 
   13567             :   // JS @@toStringTag value
   13568             :   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
   13569             :   {
   13570           5 :     TryCatch try_catch(isolate);
   13571             :     value = obj.As<v8::Object>()
   13572           5 :                 ->ObjectProtoToString(context.local())
   13573           5 :                 .ToLocalChecked();
   13574          15 :     CHECK(value->IsString() &&
   13575             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13576           5 :     CHECK(!try_catch.HasCaught());
   13577             :   }
   13578             : 
   13579             :   // JS @@toStringTag getter throws
   13580             :   obj = CompileRun(
   13581             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13582             :       "  get: function() { throw 'Test'; }"
   13583             :       "}); obj");
   13584             :   {
   13585           5 :     TryCatch try_catch(isolate);
   13586          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13587           5 :     CHECK(try_catch.HasCaught());
   13588             :   }
   13589             : 
   13590             :   // JS @@toStringTag getter does not throw
   13591             :   obj = CompileRun(
   13592             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13593             :       "  get: function() { return 'Test'; }"
   13594             :       "}); obj");
   13595             :   {
   13596           5 :     TryCatch try_catch(isolate);
   13597             :     value = obj.As<v8::Object>()
   13598           5 :                 ->ObjectProtoToString(context.local())
   13599           5 :                 .ToLocalChecked();
   13600          15 :     CHECK(value->IsString() &&
   13601             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13602           5 :     CHECK(!try_catch.HasCaught());
   13603           5 :   }
   13604           5 : }
   13605             : 
   13606             : 
   13607       23724 : THREADED_TEST(ObjectGetConstructorName) {
   13608           6 :   v8::Isolate* isolate = CcTest::isolate();
   13609           6 :   LocalContext context;
   13610          12 :   v8::HandleScope scope(isolate);
   13611             :   v8_compile(
   13612             :       "function Parent() {};"
   13613             :       "function Child() {};"
   13614             :       "Child.prototype = new Parent();"
   13615             :       "Child.prototype.constructor = Child;"
   13616             :       "var outer = { inner: (0, function() { }) };"
   13617             :       "var p = new Parent();"
   13618             :       "var c = new Child();"
   13619             :       "var x = new outer.inner();"
   13620             :       "var proto = Child.prototype;")
   13621           6 :       ->Run(context.local())
   13622           6 :       .ToLocalChecked();
   13623             : 
   13624             :   Local<v8::Value> p =
   13625          30 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13626          30 :   CHECK(p->IsObject() &&
   13627             :         p->ToObject(context.local())
   13628             :             .ToLocalChecked()
   13629             :             ->GetConstructorName()
   13630             :             ->Equals(context.local(), v8_str("Parent"))
   13631             :             .FromJust());
   13632             : 
   13633             :   Local<v8::Value> c =
   13634          30 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13635          30 :   CHECK(c->IsObject() &&
   13636             :         c->ToObject(context.local())
   13637             :             .ToLocalChecked()
   13638             :             ->GetConstructorName()
   13639             :             ->Equals(context.local(), v8_str("Child"))
   13640             :             .FromJust());
   13641             : 
   13642             :   Local<v8::Value> x =
   13643          30 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
   13644          30 :   CHECK(x->IsObject() &&
   13645             :         x->ToObject(context.local())
   13646             :             .ToLocalChecked()
   13647             :             ->GetConstructorName()
   13648             :             ->Equals(context.local(), v8_str("outer.inner"))
   13649             :             .FromJust());
   13650             : 
   13651             :   Local<v8::Value> child_prototype =
   13652          30 :       context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
   13653          30 :   CHECK(child_prototype->IsObject() &&
   13654             :         child_prototype->ToObject(context.local())
   13655             :             .ToLocalChecked()
   13656             :             ->GetConstructorName()
   13657             :             ->Equals(context.local(), v8_str("Parent"))
   13658           6 :             .FromJust());
   13659           6 : }
   13660             : 
   13661             : 
   13662       23724 : THREADED_TEST(SubclassGetConstructorName) {
   13663           6 :   v8::Isolate* isolate = CcTest::isolate();
   13664           6 :   LocalContext context;
   13665          12 :   v8::HandleScope scope(isolate);
   13666             :   v8_compile(
   13667             :       "\"use strict\";"
   13668             :       "class Parent {}"
   13669             :       "class Child extends Parent {}"
   13670             :       "var p = new Parent();"
   13671             :       "var c = new Child();")
   13672           6 :       ->Run(context.local())
   13673           6 :       .ToLocalChecked();
   13674             : 
   13675             :   Local<v8::Value> p =
   13676          30 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13677          30 :   CHECK(p->IsObject() &&
   13678             :         p->ToObject(context.local())
   13679             :             .ToLocalChecked()
   13680             :             ->GetConstructorName()
   13681             :             ->Equals(context.local(), v8_str("Parent"))
   13682             :             .FromJust());
   13683             : 
   13684             :   Local<v8::Value> c =
   13685          30 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13686          30 :   CHECK(c->IsObject() &&
   13687             :         c->ToObject(context.local())
   13688             :             .ToLocalChecked()
   13689             :             ->GetConstructorName()
   13690             :             ->Equals(context.local(), v8_str("Child"))
   13691           6 :             .FromJust());
   13692           6 : }
   13693             : 
   13694             : 
   13695             : bool ApiTestFuzzer::fuzzing_ = false;
   13696       23718 : v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13697             : int ApiTestFuzzer::active_tests_;
   13698             : int ApiTestFuzzer::tests_being_run_;
   13699             : int ApiTestFuzzer::current_;
   13700             : 
   13701             : 
   13702             : // We are in a callback and want to switch to another thread (if we
   13703             : // are currently running the thread fuzzing test).
   13704      470793 : void ApiTestFuzzer::Fuzz() {
   13705      941586 :   if (!fuzzing_) return;
   13706       77223 :   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13707       77223 :   test->ContextSwitch();
   13708             : }
   13709             : 
   13710             : 
   13711             : // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13712             : // not start immediately.
   13713       77694 : bool ApiTestFuzzer::NextThread() {
   13714       77694 :   int test_position = GetNextTestNumber();
   13715       77694 :   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13716       77694 :   if (test_position == current_) {
   13717             :     if (kLogThreading)
   13718             :       printf("Stay with %s\n", test_name);
   13719             :     return false;
   13720             :   }
   13721             :   if (kLogThreading) {
   13722             :     printf("Switch from %s to %s\n",
   13723             :            test_name,
   13724             :            RegisterThreadedTest::nth(test_position)->name());
   13725             :   }
   13726       23568 :   current_ = test_position;
   13727       23568 :   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13728       23568 :   return true;
   13729             : }
   13730             : 
   13731             : 
   13732         471 : void ApiTestFuzzer::Run() {
   13733             :   // When it is our turn...
   13734         471 :   gate_.Wait();
   13735             :   {
   13736             :     // ... get the V8 lock and start running the test.
   13737         471 :     v8::Locker locker(CcTest::isolate());
   13738         471 :     CallTest();
   13739             :   }
   13740             :   // This test finished.
   13741         471 :   active_ = false;
   13742         471 :   active_tests_--;
   13743             :   // If it was the last then signal that fact.
   13744         471 :   if (active_tests_ == 0) {
   13745           8 :     all_tests_done_.Signal();
   13746             :   } else {
   13747             :     // Otherwise select a new test and start that.
   13748         463 :     NextThread();
   13749             :   }
   13750         471 : }
   13751             : 
   13752             : 
   13753             : static unsigned linear_congruential_generator;
   13754             : 
   13755             : 
   13756           8 : void ApiTestFuzzer::SetUp(PartOfTest part) {
   13757           8 :   linear_congruential_generator = i::FLAG_testing_prng_seed;
   13758           8 :   fuzzing_ = true;
   13759             :   int count = RegisterThreadedTest::count();
   13760           8 :   int start =  count * part / (LAST_PART + 1);
   13761           8 :   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   13762           8 :   active_tests_ = tests_being_run_ = end - start + 1;
   13763         479 :   for (int i = 0; i < tests_being_run_; i++) {
   13764         471 :     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   13765             :   }
   13766         471 :   for (int i = 0; i < active_tests_; i++) {
   13767         471 :     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   13768             :   }
   13769           8 : }
   13770             : 
   13771             : 
   13772             : static void CallTestNumber(int test_number) {
   13773         471 :   (RegisterThreadedTest::nth(test_number)->callback())();
   13774             : }
   13775             : 
   13776             : 
   13777           0 : void ApiTestFuzzer::RunAllTests() {
   13778             :   // Set off the first test.
   13779           8 :   current_ = -1;
   13780           8 :   NextThread();
   13781             :   // Wait till they are all done.
   13782           8 :   all_tests_done_.Wait();
   13783           0 : }
   13784             : 
   13785             : 
   13786       77694 : int ApiTestFuzzer::GetNextTestNumber() {
   13787             :   int next_test;
   13788     3188791 :   do {
   13789     3188791 :     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   13790     3188791 :     linear_congruential_generator *= 1664525u;
   13791     3188791 :     linear_congruential_generator += 1013904223u;
   13792     3188791 :   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   13793       77694 :   return next_test;
   13794             : }
   13795             : 
   13796             : 
   13797       77223 : void ApiTestFuzzer::ContextSwitch() {
   13798             :   // If the new thread is the same as the current thread there is nothing to do.
   13799       77223 :   if (NextThread()) {
   13800             :     // Now it can start.
   13801       23097 :     v8::Unlocker unlocker(CcTest::isolate());
   13802             :     // Wait till someone starts us again.
   13803       23097 :     gate_.Wait();
   13804             :     // And we're off.
   13805             :   }
   13806       77223 : }
   13807             : 
   13808             : 
   13809           8 : void ApiTestFuzzer::TearDown() {
   13810           8 :   fuzzing_ = false;
   13811        7552 :   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   13812        3768 :     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   13813        3768 :     if (fuzzer != nullptr) fuzzer->Join();
   13814             :   }
   13815           8 : }
   13816             : 
   13817         471 : void ApiTestFuzzer::CallTest() {
   13818         471 :   v8::Isolate::Scope scope(CcTest::isolate());
   13819             :   if (kLogThreading)
   13820             :     printf("Start test %s #%d\n",
   13821             :            RegisterThreadedTest::nth(test_number_)->name(), test_number_);
   13822         471 :   CallTestNumber(test_number_);
   13823             :   if (kLogThreading)
   13824             :     printf("End test %s #%d\n", RegisterThreadedTest::nth(test_number_)->name(),
   13825             :            test_number_);
   13826         471 : }
   13827             : 
   13828             : #define THREADING_TEST(INDEX, NAME)            \
   13829             :   TEST(Threading##INDEX) {                     \
   13830             :     ApiTestFuzzer::SetUp(ApiTestFuzzer::NAME); \
   13831             :     ApiTestFuzzer::RunAllTests();              \
   13832             :     ApiTestFuzzer::TearDown();                 \
   13833             :   }
   13834             : 
   13835       23720 : THREADING_TEST(1, FIRST_PART)
   13836       23720 : THREADING_TEST(2, SECOND_PART)
   13837       23720 : THREADING_TEST(3, THIRD_PART)
   13838       23720 : THREADING_TEST(4, FOURTH_PART)
   13839       23720 : THREADING_TEST(5, FIFTH_PART)
   13840       23720 : THREADING_TEST(6, SIXTH_PART)
   13841       23720 : THREADING_TEST(7, SEVENTH_PART)
   13842       23720 : THREADING_TEST(8, EIGHTH_PART)
   13843             : 
   13844             : #undef THREADING_TEST
   13845             : 
   13846          10 : static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13847             :   v8::Isolate* isolate = args.GetIsolate();
   13848           5 :   CHECK(v8::Locker::IsLocked(isolate));
   13849           5 :   ApiTestFuzzer::Fuzz();
   13850             :   v8::Unlocker unlocker(isolate);
   13851             :   const char* code = "throw 7;";
   13852             :   {
   13853             :     v8::Locker nested_locker(isolate);
   13854          10 :     v8::HandleScope scope(isolate);
   13855             :     v8::Local<Value> exception;
   13856             :     {
   13857           5 :       v8::TryCatch try_catch(isolate);
   13858             :       v8::Local<Value> value = CompileRun(code);
   13859           5 :       CHECK(value.IsEmpty());
   13860           5 :       CHECK(try_catch.HasCaught());
   13861             :       // Make sure to wrap the exception in a new handle because
   13862             :       // the handle returned from the TryCatch is destroyed
   13863             :       // when the TryCatch is destroyed.
   13864          10 :       exception = Local<Value>::New(isolate, try_catch.Exception());
   13865             :     }
   13866          10 :     args.GetIsolate()->ThrowException(exception);
   13867           5 :   }
   13868           5 : }
   13869             : 
   13870             : 
   13871          15 : static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13872           5 :   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13873           5 :   ApiTestFuzzer::Fuzz();
   13874           5 :   v8::Unlocker unlocker(CcTest::isolate());
   13875             :   const char* code = "throw 7;";
   13876             :   {
   13877           5 :     v8::Locker nested_locker(CcTest::isolate());
   13878          10 :     v8::HandleScope scope(args.GetIsolate());
   13879             :     v8::Local<Value> value = CompileRun(code);
   13880           5 :     CHECK(value.IsEmpty());
   13881          10 :     args.GetReturnValue().Set(v8_str("foo"));
   13882           5 :   }
   13883           5 : }
   13884             : 
   13885             : 
   13886             : // These are locking tests that don't need to be run again
   13887             : // as part of the locking aggregation tests.
   13888       23723 : TEST(NestedLockers) {
   13889           5 :   v8::Isolate* isolate = CcTest::isolate();
   13890             :   v8::Locker locker(isolate);
   13891           5 :   CHECK(v8::Locker::IsLocked(isolate));
   13892          10 :   LocalContext env;
   13893          10 :   v8::HandleScope scope(env->GetIsolate());
   13894             :   Local<v8::FunctionTemplate> fun_templ =
   13895           5 :       v8::FunctionTemplate::New(isolate, ThrowInJS);
   13896          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13897          25 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13898             :   Local<Script> script = v8_compile("(function () {"
   13899             :                                     "  try {"
   13900             :                                     "    throw_in_js();"
   13901             :                                     "    return 42;"
   13902             :                                     "  } catch (e) {"
   13903             :                                     "    return e * 13;"
   13904             :                                     "  }"
   13905             :                                     "})();");
   13906          15 :   CHECK_EQ(91, script->Run(env.local())
   13907             :                    .ToLocalChecked()
   13908             :                    ->Int32Value(env.local())
   13909           5 :                    .FromJust());
   13910           5 : }
   13911             : 
   13912             : 
   13913             : // These are locking tests that don't need to be run again
   13914             : // as part of the locking aggregation tests.
   13915       23723 : TEST(NestedLockersNoTryCatch) {
   13916           5 :   v8::Locker locker(CcTest::isolate());
   13917          10 :   LocalContext env;
   13918          10 :   v8::HandleScope scope(env->GetIsolate());
   13919             :   Local<v8::FunctionTemplate> fun_templ =
   13920           5 :       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   13921          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13922          25 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13923             :   Local<Script> script = v8_compile("(function () {"
   13924             :                                     "  try {"
   13925             :                                     "    throw_in_js();"
   13926             :                                     "    return 42;"
   13927             :                                     "  } catch (e) {"
   13928             :                                     "    return e * 13;"
   13929             :                                     "  }"
   13930             :                                     "})();");
   13931          15 :   CHECK_EQ(91, script->Run(env.local())
   13932             :                    .ToLocalChecked()
   13933             :                    ->Int32Value(env.local())
   13934           5 :                    .FromJust());
   13935           5 : }
   13936             : 
   13937             : 
   13938       23724 : THREADED_TEST(RecursiveLocking) {
   13939           6 :   v8::Locker locker(CcTest::isolate());
   13940             :   {
   13941           6 :     v8::Locker locker2(CcTest::isolate());
   13942           6 :     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13943           6 :   }
   13944           6 : }
   13945             : 
   13946             : 
   13947          12 : static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13948          12 :   ApiTestFuzzer::Fuzz();
   13949          24 :   v8::Unlocker unlocker(CcTest::isolate());
   13950          12 : }
   13951             : 
   13952             : 
   13953       23724 : THREADED_TEST(LockUnlockLock) {
   13954             :   {
   13955           6 :     v8::Locker locker(CcTest::isolate());
   13956          12 :     v8::HandleScope scope(CcTest::isolate());
   13957          12 :     LocalContext env;
   13958             :     Local<v8::FunctionTemplate> fun_templ =
   13959           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13960          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13961          30 :     CHECK(env->Global()
   13962             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13963             :               .FromJust());
   13964             :     Local<Script> script = v8_compile("(function () {"
   13965             :                                       "  unlock_for_a_moment();"
   13966             :                                       "  return 42;"
   13967             :                                       "})();");
   13968          18 :     CHECK_EQ(42, script->Run(env.local())
   13969             :                      .ToLocalChecked()
   13970             :                      ->Int32Value(env.local())
   13971           6 :                      .FromJust());
   13972             :   }
   13973             :   {
   13974           6 :     v8::Locker locker(CcTest::isolate());
   13975          12 :     v8::HandleScope scope(CcTest::isolate());
   13976          12 :     LocalContext env;
   13977             :     Local<v8::FunctionTemplate> fun_templ =
   13978           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13979          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13980          30 :     CHECK(env->Global()
   13981             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13982             :               .FromJust());
   13983             :     Local<Script> script = v8_compile("(function () {"
   13984             :                                       "  unlock_for_a_moment();"
   13985             :                                       "  return 42;"
   13986             :                                       "})();");
   13987          18 :     CHECK_EQ(42, script->Run(env.local())
   13988             :                      .ToLocalChecked()
   13989             :                      ->Int32Value(env.local())
   13990           6 :                      .FromJust());
   13991             :   }
   13992           6 : }
   13993             : 
   13994             : 
   13995         130 : static int GetGlobalObjectsCount() {
   13996             :   int count = 0;
   13997         130 :   i::HeapIterator it(CcTest::heap());
   13998      817148 :   for (i::HeapObject* object = it.next(); object != nullptr; object = it.next())
   13999      817018 :     if (object->IsJSGlobalObject()) {
   14000             :       i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
   14001             :       // Skip dummy global object.
   14002          30 :       if (g->global_dictionary()->NumberOfElements() != 0) {
   14003          30 :         count++;
   14004             :       }
   14005             :     }
   14006         130 :   return count;
   14007             : }
   14008             : 
   14009             : 
   14010         100 : static void CheckSurvivingGlobalObjectsCount(int expected) {
   14011             :   // We need to collect all garbage twice to be sure that everything
   14012             :   // has been collected.  This is because inline caches are cleared in
   14013             :   // the first garbage collection but some of the maps have already
   14014             :   // been marked at that point.  Therefore some of the maps are not
   14015             :   // collected until the second garbage collection.
   14016         100 :   CcTest::CollectAllGarbage();
   14017         100 :   CcTest::CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
   14018         100 :   int count = GetGlobalObjectsCount();
   14019         100 :   CHECK_EQ(expected, count);
   14020         100 : }
   14021             : 
   14022             : 
   14023       23723 : TEST(DontLeakGlobalObjects) {
   14024             :   // Regression test for issues 1139850 and 1174891.
   14025             : 
   14026           5 :   i::FLAG_expose_gc = true;
   14027           5 :   v8::V8::Initialize();
   14028             : 
   14029          30 :   for (int i = 0; i < 5; i++) {
   14030          25 :     { v8::HandleScope scope(CcTest::isolate());
   14031          25 :       LocalContext context;
   14032             :     }
   14033          25 :     CcTest::isolate()->ContextDisposedNotification();
   14034          25 :     CheckSurvivingGlobalObjectsCount(0);
   14035             : 
   14036          25 :     { v8::HandleScope scope(CcTest::isolate());
   14037          50 :       LocalContext context;
   14038          75 :       v8_compile("Date")->Run(context.local()).ToLocalChecked();
   14039             :     }
   14040          25 :     CcTest::isolate()->ContextDisposedNotification();
   14041          25 :     CheckSurvivingGlobalObjectsCount(0);
   14042             : 
   14043          25 :     { v8::HandleScope scope(CcTest::isolate());
   14044          50 :       LocalContext context;
   14045          75 :       v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
   14046             :     }
   14047          25 :     CcTest::isolate()->ContextDisposedNotification();
   14048          25 :     CheckSurvivingGlobalObjectsCount(0);
   14049             : 
   14050          25 :     { v8::HandleScope scope(CcTest::isolate());
   14051          25 :       const char* extension_list[] = { "v8/gc" };
   14052             :       v8::ExtensionConfiguration extensions(1, extension_list);
   14053          50 :       LocalContext context(&extensions);
   14054          75 :       v8_compile("gc();")->Run(context.local()).ToLocalChecked();
   14055             :     }
   14056          25 :     CcTest::isolate()->ContextDisposedNotification();
   14057          25 :     CheckSurvivingGlobalObjectsCount(0);
   14058             :   }
   14059           5 : }
   14060             : 
   14061             : 
   14062       23723 : TEST(CopyablePersistent) {
   14063           5 :   LocalContext context;
   14064           5 :   v8::Isolate* isolate = context->GetIsolate();
   14065          25 :   i::GlobalHandles* globals =
   14066             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   14067             :   int initial_handles = globals->global_handles_count();
   14068             :   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   14069             :       CopyableObject;
   14070             :   {
   14071             :     CopyableObject handle1;
   14072             :     {
   14073           5 :       v8::HandleScope scope(isolate);
   14074          10 :       handle1.Reset(isolate, v8::Object::New(isolate));
   14075             :     }
   14076           5 :     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
   14077             :     CopyableObject  handle2;
   14078             :     handle2 = handle1;
   14079           5 :     CHECK(handle1 == handle2);
   14080           5 :     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
   14081             :     CopyableObject handle3(handle2);
   14082           5 :     CHECK(handle1 == handle3);
   14083           5 :     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
   14084             :   }
   14085             :   // Verify autodispose
   14086           5 :   CHECK_EQ(initial_handles, globals->global_handles_count());
   14087           5 : }
   14088             : 
   14089             : 
   14090           5 : static void WeakApiCallback(
   14091          10 :     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
   14092             :   data.GetParameter()->Reset();
   14093           5 :   delete data.GetParameter();
   14094           5 : }
   14095             : 
   14096             : 
   14097       23723 : TEST(WeakCallbackApi) {
   14098           5 :   LocalContext context;
   14099           5 :   v8::Isolate* isolate = context->GetIsolate();
   14100          10 :   i::GlobalHandles* globals =
   14101             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   14102             :   int initial_handles = globals->global_handles_count();
   14103             :   {
   14104           5 :     v8::HandleScope scope(isolate);
   14105           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   14106          25 :     CHECK(
   14107             :         obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
   14108             :             .FromJust());
   14109             :     v8::Persistent<v8::Object>* handle =
   14110           5 :         new v8::Persistent<v8::Object>(isolate, obj);
   14111             :     handle->SetWeak<v8::Persistent<v8::Object>>(
   14112           5 :         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
   14113             :   }
   14114             :   reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
   14115             :       i::Heap::kAbortIncrementalMarkingMask,
   14116           5 :       i::GarbageCollectionReason::kTesting);
   14117             :   // Verify disposed.
   14118           5 :   CHECK_EQ(initial_handles, globals->global_handles_count());
   14119           5 : }
   14120             : 
   14121             : 
   14122       23718 : v8::Persistent<v8::Object> some_object;
   14123       23718 : v8::Persistent<v8::Object> bad_handle;
   14124             : 
   14125             : 
   14126           6 : void NewPersistentHandleCallback2(
   14127          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14128           6 :   v8::HandleScope scope(data.GetIsolate());
   14129           6 :   bad_handle.Reset(data.GetIsolate(), some_object);
   14130           6 : }
   14131             : 
   14132             : 
   14133           6 : void NewPersistentHandleCallback1(
   14134          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14135             :   data.GetParameter()->Reset();
   14136             :   data.SetSecondPassCallback(NewPersistentHandleCallback2);
   14137           6 : }
   14138             : 
   14139             : 
   14140       23724 : THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   14141           6 :   LocalContext context;
   14142           6 :   v8::Isolate* isolate = context->GetIsolate();
   14143             : 
   14144             :   v8::Persistent<v8::Object> handle1, handle2;
   14145             :   {
   14146           6 :     v8::HandleScope scope(isolate);
   14147          12 :     some_object.Reset(isolate, v8::Object::New(isolate));
   14148          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   14149          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   14150             :   }
   14151             :   // Note: order is implementation dependent alas: currently
   14152             :   // global handle nodes are processed by PostGarbageCollectionProcessing
   14153             :   // in reverse allocation order, so if second allocated handle is deleted,
   14154             :   // weak callback of the first handle would be able to 'reallocate' it.
   14155             :   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
   14156             :                   v8::WeakCallbackType::kParameter);
   14157             :   handle2.Reset();
   14158           6 :   CcTest::CollectAllGarbage();
   14159           6 : }
   14160             : 
   14161             : 
   14162       23718 : v8::Persistent<v8::Object> to_be_disposed;
   14163             : 
   14164             : 
   14165           6 : void DisposeAndForceGcCallback2(
   14166             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14167             :   to_be_disposed.Reset();
   14168           6 :   CcTest::CollectAllGarbage();
   14169           6 : }
   14170             : 
   14171             : 
   14172           6 : void DisposeAndForceGcCallback1(
   14173          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14174             :   data.GetParameter()->Reset();
   14175             :   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
   14176           6 : }
   14177             : 
   14178             : 
   14179       23724 : THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   14180           6 :   LocalContext context;
   14181           6 :   v8::Isolate* isolate = context->GetIsolate();
   14182             : 
   14183             :   v8::Persistent<v8::Object> handle1, handle2;
   14184             :   {
   14185           6 :     v8::HandleScope scope(isolate);
   14186          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   14187          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   14188             :   }
   14189             :   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
   14190             :                   v8::WeakCallbackType::kParameter);
   14191             :   to_be_disposed.Reset(isolate, handle2);
   14192           6 :   CcTest::CollectAllGarbage();
   14193           6 : }
   14194             : 
   14195           6 : void DisposingCallback(
   14196           6 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14197             :   data.GetParameter()->Reset();
   14198           6 : }
   14199             : 
   14200           6 : void HandleCreatingCallback2(
   14201          18 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14202           6 :   v8::HandleScope scope(data.GetIsolate());
   14203          12 :   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
   14204           6 : }
   14205             : 
   14206             : 
   14207           6 : void HandleCreatingCallback1(
   14208          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14209             :   data.GetParameter()->Reset();
   14210             :   data.SetSecondPassCallback(HandleCreatingCallback2);
   14211           6 : }
   14212             : 
   14213             : 
   14214       23724 : THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   14215           6 :   v8::Locker locker(CcTest::isolate());
   14216          12 :   LocalContext context;
   14217           6 :   v8::Isolate* isolate = context->GetIsolate();
   14218             : 
   14219             :   v8::Persistent<v8::Object> handle1, handle2, handle3;
   14220             :   {
   14221           6 :     v8::HandleScope scope(isolate);
   14222          12 :     handle3.Reset(isolate, v8::Object::New(isolate));
   14223          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   14224          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   14225             :   }
   14226             :   handle2.SetWeak(&handle2, DisposingCallback,
   14227             :                   v8::WeakCallbackType::kParameter);
   14228             :   handle3.SetWeak(&handle3, HandleCreatingCallback1,
   14229             :                   v8::WeakCallbackType::kParameter);
   14230           6 :   CcTest::CollectAllGarbage();
   14231          12 :   EmptyMessageQueues(isolate);
   14232           6 : }
   14233             : 
   14234             : 
   14235       23724 : THREADED_TEST(CheckForCrossContextObjectLiterals) {
   14236           6 :   v8::V8::Initialize();
   14237             : 
   14238             :   const int nof = 2;
   14239             :   const char* sources[nof] = {
   14240             :     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   14241             :     "Object()"
   14242           6 :   };
   14243             : 
   14244          18 :   for (int i = 0; i < nof; i++) {
   14245          12 :     const char* source = sources[i];
   14246          12 :     { v8::HandleScope scope(CcTest::isolate());
   14247          24 :       LocalContext context;
   14248          12 :       CompileRun(source);
   14249             :     }
   14250          12 :     { v8::HandleScope scope(CcTest::isolate());
   14251          24 :       LocalContext context;
   14252          12 :       CompileRun(source);
   14253             :     }
   14254             :   }
   14255           6 : }
   14256             : 
   14257             : 
   14258           6 : static v8::Local<Value> NestedScope(v8::Local<Context> env) {
   14259           6 :   v8::EscapableHandleScope inner(env->GetIsolate());
   14260           6 :   env->Enter();
   14261           6 :   v8::Local<Value> three = v8_num(3);
   14262             :   v8::Local<Value> value = inner.Escape(three);
   14263           6 :   env->Exit();
   14264          12 :   return value;
   14265             : }
   14266             : 
   14267             : 
   14268       23724 : THREADED_TEST(NestedHandleScopeAndContexts) {
   14269           6 :   v8::Isolate* isolate = CcTest::isolate();
   14270           6 :   v8::HandleScope outer(isolate);
   14271           6 :   v8::Local<Context> env = Context::New(isolate);
   14272           6 :   env->Enter();
   14273           6 :   v8::Local<Value> value = NestedScope(env);
   14274           6 :   v8::Local<String> str(value->ToString(env).ToLocalChecked());
   14275           6 :   CHECK(!str.IsEmpty());
   14276           6 :   env->Exit();
   14277           6 : }
   14278             : 
   14279             : 
   14280             : struct SymbolInfo {
   14281             :   size_t id;
   14282             :   size_t size;
   14283             :   std::string name;
   14284             : };
   14285             : 
   14286             : 
   14287             : class SetFunctionEntryHookTest {
   14288             :  public:
   14289           0 :   SetFunctionEntryHookTest() {
   14290           0 :     CHECK_NULL(instance_);
   14291           0 :     instance_ = this;
   14292           0 :   }
   14293           0 :   ~SetFunctionEntryHookTest() {
   14294           0 :     CHECK(instance_ == this);
   14295           0 :     instance_ = nullptr;
   14296           0 :   }
   14297           0 :   void Reset() {
   14298             :     symbols_.clear();
   14299             :     symbol_locations_.clear();
   14300             :     invocations_.clear();
   14301           0 :   }
   14302             :   void RunTest();
   14303             :   void OnJitEvent(const v8::JitCodeEvent* event);
   14304           0 :   static void JitEvent(const v8::JitCodeEvent* event) {
   14305           0 :     CHECK_NOT_NULL(instance_);
   14306           0 :     instance_->OnJitEvent(event);
   14307           0 :   }
   14308             : 
   14309             :   void OnEntryHook(uintptr_t function,
   14310             :                    uintptr_t return_addr_location);
   14311           0 :   static void EntryHook(uintptr_t function,
   14312             :                         uintptr_t return_addr_location) {
   14313           0 :     CHECK_NOT_NULL(instance_);
   14314           0 :     instance_->OnEntryHook(function, return_addr_location);
   14315           0 :   }
   14316             : 
   14317           0 :   static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   14318           0 :     CHECK_NOT_NULL(instance_);
   14319           0 :     args.GetReturnValue().Set(v8_num(42));
   14320           0 :   }
   14321             :   void RunLoopInNewEnv(v8::Isolate* isolate);
   14322             : 
   14323             :   // Records addr as location of symbol.
   14324             :   void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
   14325             : 
   14326             :   // Finds the symbol containing addr
   14327             :   SymbolInfo* FindSymbolForAddr(i::Address addr);
   14328             :   // Returns the number of invocations where the caller name contains
   14329             :   // \p caller_name and the function name contains \p function_name.
   14330             :   int CountInvocations(const char* caller_name,
   14331             :                        const char* function_name);
   14332             : 
   14333             :   i::Handle<i::JSFunction> foo_func_;
   14334             :   i::Handle<i::JSFunction> bar_func_;
   14335             : 
   14336             :   typedef std::map<size_t, SymbolInfo> SymbolMap;
   14337             :   typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
   14338             :   typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
   14339             :   SymbolMap symbols_;
   14340             :   SymbolLocationMap symbol_locations_;
   14341             :   InvocationMap invocations_;
   14342             : 
   14343             :   static SetFunctionEntryHookTest* instance_;
   14344             : };
   14345             : SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = nullptr;
   14346             : 
   14347             : // Returns true if addr is in the range [start, start+len).
   14348             : static bool Overlaps(i::Address start, size_t len, i::Address addr) {
   14349           0 :   if (start <= addr && start + len > addr)
   14350             :     return true;
   14351             : 
   14352             :   return false;
   14353             : }
   14354             : 
   14355           0 : void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
   14356             :                                               SymbolInfo* symbol) {
   14357             :   // Insert the symbol at the new location.
   14358             :   SymbolLocationMap::iterator it =
   14359           0 :       symbol_locations_.insert(std::make_pair(addr, symbol)).first;
   14360             :   // Now erase symbols to the left and right that overlap this one.
   14361           0 :   while (it != symbol_locations_.begin()) {
   14362             :     SymbolLocationMap::iterator left = it;
   14363             :     --left;
   14364           0 :     if (!Overlaps(left->first, left->second->size, addr))
   14365             :       break;
   14366             :     symbol_locations_.erase(left);
   14367             :   }
   14368             : 
   14369             :   // Now erase symbols to the left and right that overlap this one.
   14370             :   while (true) {
   14371             :     SymbolLocationMap::iterator right = it;
   14372             :     ++right;
   14373           0 :     if (right == symbol_locations_.end())
   14374             :         break;
   14375           0 :     if (!Overlaps(addr, symbol->size, right->first))
   14376             :       break;
   14377             :     symbol_locations_.erase(right);
   14378           0 :   }
   14379           0 : }
   14380             : 
   14381             : 
   14382           0 : void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
   14383           0 :   switch (event->type) {
   14384             :     case v8::JitCodeEvent::CODE_ADDED: {
   14385           0 :       CHECK_NOT_NULL(event->code_start);
   14386           0 :       CHECK_NE(0, static_cast<int>(event->code_len));
   14387           0 :       CHECK_NOT_NULL(event->name.str);
   14388           0 :       size_t symbol_id = symbols_.size();
   14389             : 
   14390             :       // Record the new symbol.
   14391           0 :       SymbolInfo& info = symbols_[symbol_id];
   14392           0 :       info.id = symbol_id;
   14393           0 :       info.size = event->code_len;
   14394           0 :       info.name.assign(event->name.str, event->name.str + event->name.len);
   14395             : 
   14396             :       // And record it's location.
   14397           0 :       InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
   14398             :       }
   14399           0 :       break;
   14400             : 
   14401             :     case v8::JitCodeEvent::CODE_MOVED: {
   14402             :         // We would like to never see code move that we haven't seen before,
   14403             :         // but the code creation event does not happen until the line endings
   14404             :         // have been calculated (this is so that we can report the line in the
   14405             :         // script at which the function source is found, see
   14406             :         // Compiler::RecordFunctionCompilation) and the line endings
   14407             :         // calculations can cause a GC, which can move the newly created code
   14408             :         // before its existence can be logged.
   14409             :         SymbolLocationMap::iterator it(
   14410             :             symbol_locations_.find(
   14411           0 :                 reinterpret_cast<i::Address>(event->code_start)));
   14412           0 :         if (it != symbol_locations_.end()) {
   14413             :           // Found a symbol at this location, move it.
   14414           0 :           SymbolInfo* info = it->second;
   14415             :           symbol_locations_.erase(it);
   14416             :           InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
   14417           0 :                          info);
   14418             :         }
   14419             :       }
   14420             :     default:
   14421             :       break;
   14422             :   }
   14423           0 : }
   14424             : 
   14425           0 : void SetFunctionEntryHookTest::OnEntryHook(
   14426             :     uintptr_t function, uintptr_t return_addr_location) {
   14427             :   // Get the function's code object.
   14428             :   i::Code* function_code = i::Code::GetCodeFromTargetAddress(
   14429           0 :       reinterpret_cast<i::Address>(function));
   14430           0 :   CHECK_NOT_NULL(function_code);
   14431             : 
   14432             :   // Then try and look up the caller's code object.
   14433           0 :   i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
   14434             : 
   14435             :   // Count the invocation.
   14436           0 :   SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
   14437             :   SymbolInfo* function_symbol =
   14438           0 :       FindSymbolForAddr(reinterpret_cast<i::Address>(function));
   14439           0 :   ++invocations_[std::make_pair(caller_symbol, function_symbol)];
   14440             : 
   14441           0 :   if (!bar_func_.is_null() && function_code == bar_func_->code()) {
   14442             :     // Check that we have a symbol for the "bar" function at the right location.
   14443             :     SymbolLocationMap::iterator it(
   14444           0 :         symbol_locations_.find(function_code->instruction_start()));
   14445           0 :     CHECK(it != symbol_locations_.end());
   14446             :   }
   14447             : 
   14448           0 :   if (!foo_func_.is_null() && function_code == foo_func_->code()) {
   14449             :     // Check that we have a symbol for "foo" at the right location.
   14450             :     SymbolLocationMap::iterator it(
   14451           0 :         symbol_locations_.find(function_code->instruction_start()));
   14452           0 :     CHECK(it != symbol_locations_.end());
   14453             :   }
   14454           0 : }
   14455             : 
   14456             : 
   14457           0 : SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
   14458             :   SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
   14459             :   // Do we have a direct hit on a symbol?
   14460           0 :   if (it != symbol_locations_.end()) {
   14461           0 :     if (it->first == addr)
   14462           0 :       return it->second;
   14463             :   }
   14464             : 
   14465             :   // If not a direct hit, it'll have to be the previous symbol.
   14466           0 :   if (it == symbol_locations_.begin()) return nullptr;
   14467             : 
   14468             :   --it;
   14469           0 :   size_t offs = addr - it->first;
   14470           0 :   if (offs < it->second->size)
   14471           0 :     return it->second;
   14472             : 
   14473             :   return nullptr;
   14474             : }
   14475             : 
   14476             : 
   14477           0 : int SetFunctionEntryHookTest::CountInvocations(
   14478             :     const char* caller_name, const char* function_name) {
   14479             :   InvocationMap::iterator it(invocations_.begin());
   14480             :   int invocations = 0;
   14481           0 :   for (; it != invocations_.end(); ++it) {
   14482           0 :     SymbolInfo* caller = it->first.first;
   14483           0 :     SymbolInfo* function = it->first.second;
   14484             : 
   14485             :     // Filter out non-matching functions.
   14486           0 :     if (function_name != nullptr) {
   14487           0 :       if (function->name.find(function_name) == std::string::npos)
   14488             :         continue;
   14489             :     }
   14490             : 
   14491             :     // Filter out non-matching callers.
   14492           0 :     if (caller_name != nullptr) {
   14493           0 :       if (caller == nullptr) continue;
   14494           0 :       if (caller->name.find(caller_name) == std::string::npos)
   14495             :         continue;
   14496             :     }
   14497             : 
   14498             :     // It matches add the invocation count to the tally.
   14499           0 :     invocations += it->second;
   14500             :   }
   14501             : 
   14502           0 :   return invocations;
   14503             : }
   14504             : 
   14505           0 : void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   14506           0 :   v8::HandleScope outer(isolate);
   14507           0 :   v8::Local<Context> env = Context::New(isolate);
   14508           0 :   env->Enter();
   14509             : 
   14510           0 :   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14511           0 :   t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
   14512           0 :   CHECK(env->Global()
   14513             :             ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
   14514             :             .FromJust());
   14515             : 
   14516             :   const char* script =
   14517             :       "function bar() {\n"
   14518             :       "  var sum = 0;\n"
   14519             :       "  for (i = 0; i < 100; ++i)\n"
   14520             :       "    sum = foo(i);\n"
   14521             :       "  return sum;\n"
   14522             :       "}\n"
   14523             :       "function foo(i) { return i * i; }\n"
   14524             :       "// Invoke on the runtime function.\n"
   14525             :       "obj.asdf()";
   14526             :   CompileRun(script);
   14527             :   bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
   14528           0 :       *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
   14529           0 :   CHECK(!bar_func_.is_null());
   14530             : 
   14531             :   foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
   14532           0 :       *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
   14533           0 :   CHECK(!foo_func_.is_null());
   14534             : 
   14535             :   v8::Local<v8::Value> value = CompileRun("bar();");
   14536           0 :   CHECK(value->IsNumber());
   14537           0 :   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14538             : 
   14539             :   // Test the optimized codegen path.
   14540             :   value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
   14541             :                      "bar();");
   14542           0 :   CHECK(value->IsNumber());
   14543           0 :   CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
   14544             : 
   14545           0 :   env->Exit();
   14546           0 : }
   14547             : 
   14548             : 
   14549           0 : void SetFunctionEntryHookTest::RunTest() {
   14550             :   // Work in a new isolate throughout.
   14551             :   v8::Isolate::CreateParams create_params;
   14552           0 :   create_params.entry_hook = EntryHook;
   14553           0 :   create_params.code_event_handler = JitEvent;
   14554           0 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14555           0 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14556             : 
   14557             :   {
   14558             :     v8::Isolate::Scope scope(isolate);
   14559             : 
   14560           0 :     RunLoopInNewEnv(isolate);
   14561             : 
   14562             :     // Check the expected invocation counts.
   14563           0 :     if (i::FLAG_always_opt) {
   14564           0 :       CHECK_EQ(2, CountInvocations(nullptr, "bar"));
   14565           0 :       CHECK_EQ(200, CountInvocations("bar", "foo"));
   14566           0 :       CHECK_EQ(200, CountInvocations(nullptr, "foo"));
   14567           0 :     } else if (i::FLAG_opt) {
   14568             :       // For ignition we don't see the actual functions being called, instead
   14569             :       // we see the InterpreterEntryTrampoline at least 102 times
   14570             :       // (100 unoptimized calls to foo, and 2 calls to bar).
   14571           0 :       CHECK_LE(102, CountInvocations(nullptr, "InterpreterEntryTrampoline"));
   14572             :       // We should also see the calls to the optimized function foo.
   14573           0 :       CHECK_EQ(100, CountInvocations(nullptr, "foo"));
   14574             :     } else {
   14575             :       // For ignition without an optimizing compiler, we should only see the
   14576             :       // InterpreterEntryTrampoline.
   14577             :       // (200 unoptimized calls to foo, and 2 calls to bar).
   14578           0 :       CHECK_LE(202, CountInvocations(nullptr, "InterpreterEntryTrampoline"));
   14579             :     }
   14580             : 
   14581             :     // Verify that we have an entry hook on some specific stubs.
   14582           0 :     CHECK_NE(0, CountInvocations(nullptr, "CEntryStub"));
   14583           0 :     CHECK_NE(0, CountInvocations(nullptr, "JSEntryStub"));
   14584           0 :     CHECK_NE(0, CountInvocations(nullptr, "JSEntryTrampoline"));
   14585             :   }
   14586           0 :   isolate->Dispose();
   14587             : 
   14588           0 :   Reset();
   14589             : 
   14590             :   // Make sure a second isolate is unaffected by the previous entry hook.
   14591           0 :   create_params = v8::Isolate::CreateParams();
   14592           0 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14593           0 :   isolate = v8::Isolate::New(create_params);
   14594             :   {
   14595             :     v8::Isolate::Scope scope(isolate);
   14596             : 
   14597             :     // Reset the entry count to zero and set the entry hook.
   14598           0 :     RunLoopInNewEnv(isolate);
   14599             : 
   14600             :     // We should record no invocations in this isolate.
   14601           0 :     CHECK_EQ(0, static_cast<int>(invocations_.size()));
   14602             :   }
   14603             : 
   14604           0 :   isolate->Dispose();
   14605           0 : }
   14606             : 
   14607             : 
   14608       23718 : TEST(SetFunctionEntryHook) {
   14609             :   // FunctionEntryHook does not work well with experimental natives.
   14610             :   // Experimental natives are compiled during snapshot deserialization.
   14611             :   // This test breaks because InstallGetter (function from snapshot that
   14612             :   // only gets called from experimental natives) is compiled with entry hooks.
   14613           0 :   i::FLAG_allow_natives_syntax = true;
   14614           0 :   i::FLAG_turbo_inlining = false;
   14615             : 
   14616           0 :   SetFunctionEntryHookTest test;
   14617           0 :   test.RunTest();
   14618           0 : }
   14619             : 
   14620             : static v8::base::HashMap* code_map = nullptr;
   14621             : static v8::base::HashMap* jitcode_line_info = nullptr;
   14622             : static int saw_bar = 0;
   14623             : static int move_events = 0;
   14624             : 
   14625             : 
   14626        5355 : static bool FunctionNameIs(const char* expected,
   14627             :                            const v8::JitCodeEvent* event) {
   14628             :   // Log lines for functions are of the general form:
   14629             :   // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
   14630             :   // where the type is one of "*", "~" or "".
   14631             :   static const char* kPreamble;
   14632        5355 :   if (!i::FLAG_lazy) {
   14633           0 :     kPreamble = "Function:";
   14634             :   } else {
   14635        5355 :     kPreamble = "LazyCompile:";
   14636             :   }
   14637        5355 :   static size_t kPreambleLen = strlen(kPreamble);
   14638             : 
   14639       10655 :   if (event->name.len < kPreambleLen ||
   14640        5300 :       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   14641             :     return false;
   14642             :   }
   14643             : 
   14644        2753 :   const char* tail = event->name.str + kPreambleLen;
   14645        2753 :   size_t tail_len = event->name.len - kPreambleLen;
   14646        2753 :   size_t expected_len = strlen(expected);
   14647        2753 :   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   14648         148 :     --tail_len;
   14649         148 :     ++tail;
   14650             :   }
   14651             : 
   14652             :   // Check for tails like 'bar :1'.
   14653        2885 :   if (tail_len > expected_len + 2 &&
   14654         264 :       tail[expected_len] == ' ' &&
   14655         264 :       tail[expected_len + 1] == ':' &&
   14656         264 :       tail[expected_len + 2] &&
   14657         132 :       !strncmp(tail, expected, expected_len)) {
   14658             :     return true;
   14659             :   }
   14660             : 
   14661        2687 :   if (tail_len != expected_len)
   14662             :     return false;
   14663             : 
   14664          21 :   return strncmp(tail, expected, expected_len) == 0;
   14665             : }
   14666             : 
   14667             : 
   14668        7617 : static void event_handler(const v8::JitCodeEvent* event) {
   14669        7617 :   CHECK_NOT_NULL(event);
   14670        7617 :   CHECK_NOT_NULL(code_map);
   14671        7617 :   CHECK_NOT_NULL(jitcode_line_info);
   14672             : 
   14673             :   class DummyJitCodeLineInfo {
   14674             :   };
   14675             : 
   14676        7617 :   switch (event->type) {
   14677             :     case v8::JitCodeEvent::CODE_ADDED: {
   14678        5355 :       CHECK_NOT_NULL(event->code_start);
   14679        5355 :       CHECK_NE(0, static_cast<int>(event->code_len));
   14680        5355 :       CHECK_NOT_NULL(event->name.str);
   14681             :       v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
   14682        5355 :           event->code_start, i::ComputePointerHash(event->code_start));
   14683        5355 :       entry->value = reinterpret_cast<void*>(event->code_len);
   14684             : 
   14685        5355 :       if (FunctionNameIs("bar", event)) {
   14686          66 :         ++saw_bar;
   14687             :         }
   14688             :       }
   14689             :       break;
   14690             : 
   14691             :     case v8::JitCodeEvent::CODE_MOVED: {
   14692         192 :         uint32_t hash = i::ComputePointerHash(event->code_start);
   14693             :         // We would like to never see code move that we haven't seen before,
   14694             :         // but the code creation event does not happen until the line endings
   14695             :         // have been calculated (this is so that we can report the line in the
   14696             :         // script at which the function source is found, see
   14697             :         // Compiler::RecordFunctionCompilation) and the line endings
   14698             :         // calculations can cause a GC, which can move the newly created code
   14699             :         // before its existence can be logged.
   14700             :         v8::base::HashMap::Entry* entry =
   14701         192 :             code_map->Lookup(event->code_start, hash);
   14702         192 :         if (entry != nullptr) {
   14703         192 :           ++move_events;
   14704             : 
   14705         192 :           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   14706         192 :           code_map->Remove(event->code_start, hash);
   14707             : 
   14708             :           entry = code_map->LookupOrInsert(
   14709             :               event->new_code_start,
   14710         384 :               i::ComputePointerHash(event->new_code_start));
   14711         192 :           entry->value = reinterpret_cast<void*>(event->code_len);
   14712             :         }
   14713             :       }
   14714             :       break;
   14715             : 
   14716             :     case v8::JitCodeEvent::CODE_REMOVED:
   14717             :       // Object/code removal events are currently not dispatched from the GC.
   14718           0 :       CHECK(false);
   14719             :       break;
   14720             : 
   14721             :     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14722             :     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14723             :     // record it in jitcode_line_info.
   14724             :     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14725         180 :         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14726             :         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14727         180 :         temp_event->user_data = line_info;
   14728             :         v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
   14729         360 :             line_info, i::ComputePointerHash(line_info));
   14730         180 :         entry->value = reinterpret_cast<void*>(line_info);
   14731             :       }
   14732         180 :       break;
   14733             :     // For these two events, we will check whether the event->user_data
   14734             :     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14735             :     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14736             :     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14737         180 :       CHECK_NOT_NULL(event->user_data);
   14738             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14739             :       v8::base::HashMap::Entry* entry =
   14740         180 :           jitcode_line_info->Lookup(event->user_data, hash);
   14741         180 :       CHECK_NOT_NULL(entry);
   14742         180 :       delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14743             :       }
   14744         180 :       break;
   14745             : 
   14746             :     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14747        1710 :       CHECK_NOT_NULL(event->user_data);
   14748             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14749             :       v8::base::HashMap::Entry* entry =
   14750        1710 :           jitcode_line_info->Lookup(event->user_data, hash);
   14751        1710 :       CHECK_NOT_NULL(entry);
   14752             :       }
   14753             :       break;
   14754             : 
   14755             :     default:
   14756             :       // Impossible event.
   14757           0 :       CHECK(false);
   14758             :       break;
   14759             :   }
   14760        7617 : }
   14761             : 
   14762             : 
   14763       23723 : UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14764           5 :   i::FLAG_stress_compaction = true;
   14765           5 :   i::FLAG_incremental_marking = false;
   14766           5 :   if (i::FLAG_never_compact) return;
   14767             :   const char* script =
   14768             :       "function bar() {"
   14769             :       "  var sum = 0;"
   14770             :       "  for (i = 0; i < 10; ++i)"
   14771             :       "    sum = foo(i);"
   14772             :       "  return sum;"
   14773             :       "}"
   14774             :       "function foo(i) { return i; };"
   14775             :       "bar();";
   14776             : 
   14777             :   // Run this test in a new isolate to make sure we don't
   14778             :   // have remnants of state from other code.
   14779             :   v8::Isolate::CreateParams create_params;
   14780           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14781          55 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14782           5 :   isolate->Enter();
   14783             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14784           5 :   i::Heap* heap = i_isolate->heap();
   14785             : 
   14786             :   // Start with a clean slate.
   14787           5 :   heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14788             : 
   14789             :   {
   14790           5 :     v8::HandleScope scope(isolate);
   14791             :     v8::base::HashMap code;
   14792           5 :     code_map = &code;
   14793             : 
   14794             :     v8::base::HashMap lineinfo;
   14795           5 :     jitcode_line_info = &lineinfo;
   14796             : 
   14797           5 :     saw_bar = 0;
   14798           5 :     move_events = 0;
   14799             : 
   14800           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14801             : 
   14802             :     // Generate new code objects sparsely distributed across several
   14803             :     // different fragmented code-space pages.
   14804             :     const int kIterations = 10;
   14805          55 :     for (int i = 0; i < kIterations; ++i) {
   14806             :       LocalContext env(isolate);
   14807             :       i::AlwaysAllocateScope always_allocate(i_isolate);
   14808             :       CompileRun(script);
   14809             : 
   14810             :       // Keep a strong reference to the code object in the handle scope.
   14811             :       i::Handle<i::JSFunction> bar(i::Handle<i::JSFunction>::cast(
   14812             :           v8::Utils::OpenHandle(*env->Global()
   14813         200 :                                      ->Get(env.local(), v8_str("bar"))
   14814          50 :                                      .ToLocalChecked())));
   14815             :       i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   14816             :           v8::Utils::OpenHandle(*env->Global()
   14817         200 :                                      ->Get(env.local(), v8_str("foo"))
   14818          50 :                                      .ToLocalChecked())));
   14819             : 
   14820             :       i::PagedSpace* foo_owning_space = reinterpret_cast<i::PagedSpace*>(
   14821          50 :           i::Page::FromAddress(foo->abstract_code()->address())->owner());
   14822             :       i::PagedSpace* bar_owning_space = reinterpret_cast<i::PagedSpace*>(
   14823          50 :           i::Page::FromAddress(bar->abstract_code()->address())->owner());
   14824          50 :       CHECK_EQ(foo_owning_space, bar_owning_space);
   14825          50 :       i::heap::SimulateFullSpace(foo_owning_space);
   14826             : 
   14827             :       // Clear the compilation cache to get more wastage.
   14828          50 :       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14829          50 :     }
   14830             : 
   14831             :     // Force code movement.
   14832           5 :     heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14833             : 
   14834           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14835             : 
   14836           5 :     CHECK_LE(kIterations, saw_bar);
   14837           5 :     CHECK_LT(0, move_events);
   14838             : 
   14839           5 :     code_map = nullptr;
   14840          10 :     jitcode_line_info = nullptr;
   14841             :   }
   14842             : 
   14843           5 :   isolate->Exit();
   14844           5 :   isolate->Dispose();
   14845             : 
   14846             :   // Do this in a new isolate.
   14847           5 :   isolate = v8::Isolate::New(create_params);
   14848           5 :   isolate->Enter();
   14849             : 
   14850             :   // Verify that we get callbacks for existing code objects when we
   14851             :   // request enumeration of existing code.
   14852             :   {
   14853           5 :     v8::HandleScope scope(isolate);
   14854           5 :     LocalContext env(isolate);
   14855             :     CompileRun(script);
   14856             : 
   14857             :     // Now get code through initial iteration.
   14858             :     v8::base::HashMap code;
   14859           5 :     code_map = &code;
   14860             : 
   14861             :     v8::base::HashMap lineinfo;
   14862           5 :     jitcode_line_info = &lineinfo;
   14863             : 
   14864             :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14865           5 :                                     event_handler);
   14866           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14867             : 
   14868           5 :     jitcode_line_info = nullptr;
   14869             :     // We expect that we got some events. Note that if we could get code removal
   14870             :     // notifications, we could compare two collections, one created by listening
   14871             :     // from the time of creation of an isolate, and the other by subscribing
   14872             :     // with EnumExisting.
   14873           5 :     CHECK_LT(0u, code.occupancy());
   14874             : 
   14875          10 :     code_map = nullptr;
   14876             :   }
   14877             : 
   14878           5 :   isolate->Exit();
   14879           5 :   isolate->Dispose();
   14880             : }
   14881             : 
   14882       23723 : TEST(ExternalAllocatedMemory) {
   14883           5 :   v8::Isolate* isolate = CcTest::isolate();
   14884           5 :   v8::HandleScope outer(isolate);
   14885           5 :   v8::Local<Context> env(Context::New(isolate));
   14886           5 :   CHECK(!env.IsEmpty());
   14887             :   const int64_t kSize = 1024*1024;
   14888             :   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14889           5 :   CHECK_EQ(baseline + kSize,
   14890             :            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14891           5 :   CHECK_EQ(baseline,
   14892             :            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14893             :   const int64_t kTriggerGCSize =
   14894           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14895           5 :   CHECK_EQ(baseline + kTriggerGCSize,
   14896             :            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   14897          10 :   CHECK_EQ(baseline,
   14898           5 :            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
   14899           5 : }
   14900             : 
   14901             : 
   14902       23723 : TEST(Regress51719) {
   14903           5 :   i::FLAG_incremental_marking = false;
   14904           5 :   CcTest::InitializeVM();
   14905             : 
   14906             :   const int64_t kTriggerGCSize =
   14907           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14908           5 :   v8::Isolate* isolate = CcTest::isolate();
   14909             :   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
   14910           5 : }
   14911             : 
   14912             : // Regression test for issue 54, object templates with embedder fields
   14913             : // but no accessors or interceptors did not get their embedder field
   14914             : // count set on instances.
   14915       23724 : THREADED_TEST(Regress54) {
   14916           6 :   LocalContext context;
   14917           6 :   v8::Isolate* isolate = context->GetIsolate();
   14918          12 :   v8::HandleScope outer(isolate);
   14919          12 :   static v8::Persistent<v8::ObjectTemplate> templ;
   14920           6 :   if (templ.IsEmpty()) {
   14921           6 :     v8::EscapableHandleScope inner(isolate);
   14922           6 :     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14923           6 :     local->SetInternalFieldCount(1);
   14924             :     templ.Reset(isolate, inner.Escape(local));
   14925             :   }
   14926             :   v8::Local<v8::Object> result =
   14927             :       v8::Local<v8::ObjectTemplate>::New(isolate, templ)
   14928           6 :           ->NewInstance(context.local())
   14929           6 :           .ToLocalChecked();
   14930          12 :   CHECK_EQ(1, result->InternalFieldCount());
   14931           6 : }
   14932             : 
   14933             : 
   14934             : // If part of the threaded tests, this test makes ThreadingTest fail
   14935             : // on mac.
   14936       23723 : TEST(CatchStackOverflow) {
   14937           5 :   LocalContext context;
   14938          10 :   v8::HandleScope scope(context->GetIsolate());
   14939          10 :   v8::TryCatch try_catch(context->GetIsolate());
   14940             :   v8::Local<v8::Value> result = CompileRun(
   14941             :       "function f() {"
   14942             :       "  return f();"
   14943             :       "}"
   14944             :       ""
   14945             :       "f();");
   14946          10 :   CHECK(result.IsEmpty());
   14947           5 : }
   14948             : 
   14949             : 
   14950          18 : static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
   14951             :                                     const char* resource_name,
   14952             :                                     int line_offset) {
   14953          18 :   v8::HandleScope scope(CcTest::isolate());
   14954          36 :   v8::TryCatch try_catch(CcTest::isolate());
   14955          18 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   14956          36 :   CHECK(script->Run(context).IsEmpty());
   14957          18 :   CHECK(try_catch.HasCaught());
   14958          18 :   v8::Local<v8::Message> message = try_catch.Message();
   14959          18 :   CHECK(!message.IsEmpty());
   14960          36 :   CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
   14961          18 :   CHECK_EQ(91, message->GetStartPosition());
   14962          18 :   CHECK_EQ(92, message->GetEndPosition());
   14963          36 :   CHECK_EQ(2, message->GetStartColumn(context).FromJust());
   14964          36 :   CHECK_EQ(3, message->GetEndColumn(context).FromJust());
   14965             :   v8::String::Utf8Value line(CcTest::isolate(),
   14966          54 :                              message->GetSourceLine(context).ToLocalChecked());
   14967          18 :   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
   14968             :   v8::String::Utf8Value name(CcTest::isolate(),
   14969          36 :                              message->GetScriptOrigin().ResourceName());
   14970          36 :   CHECK_EQ(0, strcmp(resource_name, *name));
   14971          18 : }
   14972             : 
   14973             : 
   14974       23724 : THREADED_TEST(TryCatchSourceInfo) {
   14975           6 :   LocalContext context;
   14976          12 :   v8::HandleScope scope(context->GetIsolate());
   14977             :   v8::Local<v8::String> source = v8_str(
   14978             :       "function Foo() {\n"
   14979             :       "  return Bar();\n"
   14980             :       "}\n"
   14981             :       "\n"
   14982             :       "function Bar() {\n"
   14983             :       "  return Baz();\n"
   14984             :       "}\n"
   14985             :       "\n"
   14986             :       "function Baz() {\n"
   14987             :       "  throw 'nirk';\n"
   14988             :       "}\n"
   14989             :       "\n"
   14990           6 :       "Foo();\n");
   14991             : 
   14992             :   const char* resource_name;
   14993             :   v8::Local<v8::Script> script;
   14994             :   resource_name = "test.js";
   14995           6 :   script = CompileWithOrigin(source, resource_name);
   14996           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14997             : 
   14998             :   resource_name = "test1.js";
   14999           6 :   v8::ScriptOrigin origin1(v8_str(resource_name));
   15000             :   script =
   15001          12 :       v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
   15002           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   15003             : 
   15004             :   resource_name = "test2.js";
   15005             :   v8::ScriptOrigin origin2(v8_str(resource_name),
   15006           6 :                            v8::Integer::New(context->GetIsolate(), 7));
   15007             :   script =
   15008          12 :       v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
   15009          12 :   CheckTryCatchSourceInfo(script, resource_name, 7);
   15010           6 : }
   15011             : 
   15012             : 
   15013       23724 : THREADED_TEST(TryCatchSourceInfoForEOSError) {
   15014           6 :   LocalContext context;
   15015          12 :   v8::HandleScope scope(context->GetIsolate());
   15016          12 :   v8::TryCatch try_catch(context->GetIsolate());
   15017          12 :   CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
   15018           6 :   CHECK(try_catch.HasCaught());
   15019           6 :   v8::Local<v8::Message> message = try_catch.Message();
   15020          12 :   CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
   15021          18 :   CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
   15022           6 : }
   15023             : 
   15024             : 
   15025       23724 : THREADED_TEST(CompilationCache) {
   15026           6 :   LocalContext context;
   15027          12 :   v8::HandleScope scope(context->GetIsolate());
   15028           6 :   v8::Local<v8::String> source0 = v8_str("1234");
   15029           6 :   v8::Local<v8::String> source1 = v8_str("1234");
   15030             :   v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
   15031             :   v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
   15032           6 :   v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
   15033           6 :                                       .ToLocalChecked();  // different origin
   15034          18 :   CHECK_EQ(1234, script0->Run(context.local())
   15035             :                      .ToLocalChecked()
   15036             :                      ->Int32Value(context.local())
   15037             :                      .FromJust());
   15038          18 :   CHECK_EQ(1234, script1->Run(context.local())
   15039             :                      .ToLocalChecked()
   15040             :                      ->Int32Value(context.local())
   15041             :                      .FromJust());
   15042          18 :   CHECK_EQ(1234, script2->Run(context.local())
   15043             :                      .ToLocalChecked()
   15044             :                      ->Int32Value(context.local())
   15045           6 :                      .FromJust());
   15046           6 : }
   15047             : 
   15048             : 
   15049           0 : static void FunctionNameCallback(
   15050           0 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   15051           0 :   ApiTestFuzzer::Fuzz();
   15052           0 :   args.GetReturnValue().Set(v8_num(42));
   15053           0 : }
   15054             : 
   15055             : 
   15056       23724 : THREADED_TEST(CallbackFunctionName) {
   15057           6 :   LocalContext context;
   15058           6 :   v8::Isolate* isolate = context->GetIsolate();
   15059          12 :   v8::HandleScope scope(isolate);
   15060           6 :   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   15061             :   t->Set(v8_str("asdf"),
   15062          18 :          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   15063          36 :   CHECK(context->Global()
   15064             :             ->Set(context.local(), v8_str("obj"),
   15065             :                   t->NewInstance(context.local()).ToLocalChecked())
   15066             :             .FromJust());
   15067             :   v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
   15068           6 :   CHECK(value->IsString());
   15069          12 :   v8::String::Utf8Value name(isolate, value);
   15070          12 :   CHECK_EQ(0, strcmp("asdf", *name));
   15071           6 : }
   15072             : 
   15073             : 
   15074       23724 : THREADED_TEST(DateAccess) {
   15075           6 :   LocalContext context;
   15076          12 :   v8::HandleScope scope(context->GetIsolate());
   15077             :   v8::Local<v8::Value> date =
   15078           6 :       v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
   15079           6 :   CHECK(date->IsDate());
   15080          12 :   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   15081           6 : }
   15082             : 
   15083          24 : void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   15084             :                      unsigned index, const char* name) {
   15085          24 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15086             :   v8::Local<v8::Value> value =
   15087          48 :       properties->Get(context, v8::Integer::New(isolate, index))
   15088          24 :           .ToLocalChecked();
   15089          24 :   CHECK(value->IsSymbol());
   15090             :   v8::String::Utf8Value symbol_name(isolate,
   15091          24 :                                     Local<Symbol>::Cast(value)->Name());
   15092          24 :   CHECK_EQ(0, strcmp(name, *symbol_name));
   15093          24 : }
   15094             : 
   15095          84 : void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   15096             :                       unsigned length, const char* names[]) {
   15097          84 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15098          84 :   CHECK_EQ(length, properties->Length());
   15099         342 :   for (unsigned i = 0; i < length; i++) {
   15100             :     v8::Local<v8::Value> value =
   15101        1026 :         properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
   15102         342 :     if (names[i] == nullptr) {
   15103             :       DCHECK(value->IsSymbol());
   15104             :     } else {
   15105         318 :       v8::String::Utf8Value elm(isolate, value);
   15106         318 :       CHECK_EQ(0, strcmp(names[i], *elm));
   15107             :     }
   15108             :   }
   15109          84 : }
   15110             : 
   15111          30 : void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   15112             :                      unsigned length, const char* names[]) {
   15113          30 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15114             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   15115          60 :   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
   15116          30 :   CheckStringArray(isolate, props, length, names);
   15117          30 : }
   15118             : 
   15119             : 
   15120          24 : void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   15121             :                         unsigned elmc, const char* elmv[]) {
   15122          24 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15123             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   15124             :   v8::Local<v8::Array> props =
   15125          24 :       obj->GetOwnPropertyNames(context).ToLocalChecked();
   15126          24 :   CHECK_EQ(elmc, props->Length());
   15127          42 :   for (unsigned i = 0; i < elmc; i++) {
   15128             :     v8::String::Utf8Value elm(
   15129             :         isolate,
   15130         126 :         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   15131          42 :     CHECK_EQ(0, strcmp(elmv[i], *elm));
   15132          42 :   }
   15133          24 : }
   15134             : 
   15135             : 
   15136       23724 : THREADED_TEST(PropertyEnumeration) {
   15137           6 :   LocalContext context;
   15138           6 :   v8::Isolate* isolate = context->GetIsolate();
   15139          12 :   v8::HandleScope scope(isolate);
   15140             :   v8::Local<v8::Value> obj = CompileRun(
   15141             :       "var result = [];"
   15142             :       "result[0] = {};"
   15143             :       "result[1] = {a: 1, b: 2};"
   15144             :       "result[2] = [1, 2, 3];"
   15145             :       "var proto = {x: 1, y: 2, z: 3};"
   15146             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   15147             :       "result[3] = x;"
   15148             :       "result;");
   15149             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   15150           6 :   CHECK_EQ(4u, elms->Length());
   15151             :   int elmc0 = 0;
   15152             :   const char** elmv0 = nullptr;
   15153             :   CheckProperties(
   15154             :       isolate,
   15155          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15156          12 :       elmc0, elmv0);
   15157             :   CheckOwnProperties(
   15158             :       isolate,
   15159          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15160          12 :       elmc0, elmv0);
   15161             :   int elmc1 = 2;
   15162           6 :   const char* elmv1[] = {"a", "b"};
   15163             :   CheckProperties(
   15164             :       isolate,
   15165          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   15166          12 :       elmc1, elmv1);
   15167             :   CheckOwnProperties(
   15168             :       isolate,
   15169          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   15170          12 :       elmc1, elmv1);
   15171             :   int elmc2 = 3;
   15172           6 :   const char* elmv2[] = {"0", "1", "2"};
   15173             :   CheckProperties(
   15174             :       isolate,
   15175          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   15176          12 :       elmc2, elmv2);
   15177             :   CheckOwnProperties(
   15178             :       isolate,
   15179          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   15180          12 :       elmc2, elmv2);
   15181             :   int elmc3 = 4;
   15182           6 :   const char* elmv3[] = {"w", "z", "x", "y"};
   15183             :   CheckProperties(
   15184             :       isolate,
   15185          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   15186          12 :       elmc3, elmv3);
   15187             :   int elmc4 = 2;
   15188           6 :   const char* elmv4[] = {"w", "z"};
   15189             :   CheckOwnProperties(
   15190             :       isolate,
   15191          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   15192          18 :       elmc4, elmv4);
   15193           6 : }
   15194             : 
   15195             : 
   15196       23724 : THREADED_TEST(PropertyEnumeration2) {
   15197           6 :   LocalContext context;
   15198           6 :   v8::Isolate* isolate = context->GetIsolate();
   15199          12 :   v8::HandleScope scope(isolate);
   15200             :   v8::Local<v8::Value> obj = CompileRun(
   15201             :       "var result = [];"
   15202             :       "result[0] = {};"
   15203             :       "result[1] = {a: 1, b: 2};"
   15204             :       "result[2] = [1, 2, 3];"
   15205             :       "var proto = {x: 1, y: 2, z: 3};"
   15206             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   15207             :       "result[3] = x;"
   15208             :       "result;");
   15209             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   15210           6 :   CHECK_EQ(4u, elms->Length());
   15211             :   int elmc0 = 0;
   15212             :   const char** elmv0 = nullptr;
   15213             :   CheckProperties(
   15214             :       isolate,
   15215          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15216          12 :       elmc0, elmv0);
   15217             : 
   15218             :   v8::Local<v8::Value> val =
   15219          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
   15220             :   v8::Local<v8::Array> props =
   15221           6 :       val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
   15222           6 :   CHECK_EQ(0u, props->Length());
   15223           0 :   for (uint32_t i = 0; i < props->Length(); i++) {
   15224             :     printf("p[%u]\n", i);
   15225           6 :   }
   15226           6 : }
   15227             : 
   15228       23724 : THREADED_TEST(PropertyNames) {
   15229           6 :   LocalContext context;
   15230           6 :   v8::Isolate* isolate = context->GetIsolate();
   15231          12 :   v8::HandleScope scope(isolate);
   15232             :   v8::Local<v8::Value> result = CompileRun(
   15233             :       "var result = {0: 0, 1: 1, a: 2, b: 3};"
   15234             :       "result[Symbol('symbol')] = true;"
   15235             :       "result.__proto__ = {2: 4, 3: 5, c: 6, d: 7};"
   15236             :       "result;");
   15237             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   15238             :   v8::PropertyFilter default_filter =
   15239             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   15240             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   15241             : 
   15242             :   v8::Local<v8::Array> properties =
   15243          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   15244           6 :   const char* expected_properties1[] = {"0", "1", "a", "b", "2", "3", "c", "d"};
   15245           6 :   CheckStringArray(isolate, properties, 8, expected_properties1);
   15246             : 
   15247             :   properties =
   15248             :       object
   15249             :           ->GetPropertyNames(context.local(),
   15250             :                              v8::KeyCollectionMode::kIncludePrototypes,
   15251           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   15252          12 :           .ToLocalChecked();
   15253           6 :   CheckStringArray(isolate, properties, 8, expected_properties1);
   15254             : 
   15255             :   properties = object
   15256             :                    ->GetPropertyNames(context.local(),
   15257             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   15258             :                                       include_symbols_filter,
   15259           6 :                                       v8::IndexFilter::kIncludeIndices)
   15260          12 :                    .ToLocalChecked();
   15261             :   const char* expected_properties1_1[] = {"0", "1", "a", "b", nullptr,
   15262           6 :                                           "2", "3", "c", "d"};
   15263           6 :   CheckStringArray(isolate, properties, 9, expected_properties1_1);
   15264           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15265             : 
   15266             :   properties =
   15267             :       object
   15268             :           ->GetPropertyNames(context.local(),
   15269             :                              v8::KeyCollectionMode::kIncludePrototypes,
   15270           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   15271          12 :           .ToLocalChecked();
   15272           6 :   const char* expected_properties2[] = {"a", "b", "c", "d"};
   15273           6 :   CheckStringArray(isolate, properties, 4, expected_properties2);
   15274             : 
   15275             :   properties = object
   15276             :                    ->GetPropertyNames(context.local(),
   15277             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   15278             :                                       include_symbols_filter,
   15279           6 :                                       v8::IndexFilter::kSkipIndices)
   15280          12 :                    .ToLocalChecked();
   15281           6 :   const char* expected_properties2_1[] = {"a", "b", nullptr, "c", "d"};
   15282           6 :   CheckStringArray(isolate, properties, 5, expected_properties2_1);
   15283           6 :   CheckIsSymbolAt(isolate, properties, 2, "symbol");
   15284             : 
   15285             :   properties =
   15286             :       object
   15287             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15288           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   15289          12 :           .ToLocalChecked();
   15290           6 :   const char* expected_properties3[] = {"0", "1", "a", "b"};
   15291           6 :   CheckStringArray(isolate, properties, 4, expected_properties3);
   15292             : 
   15293             :   properties = object
   15294             :                    ->GetPropertyNames(
   15295             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15296           6 :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   15297          12 :                    .ToLocalChecked();
   15298           6 :   const char* expected_properties3_1[] = {"0", "1", "a", "b", nullptr};
   15299           6 :   CheckStringArray(isolate, properties, 5, expected_properties3_1);
   15300           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15301             : 
   15302             :   properties =
   15303             :       object
   15304             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15305           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   15306          12 :           .ToLocalChecked();
   15307           6 :   const char* expected_properties4[] = {"a", "b"};
   15308           6 :   CheckStringArray(isolate, properties, 2, expected_properties4);
   15309             : 
   15310             :   properties = object
   15311             :                    ->GetPropertyNames(
   15312             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15313           6 :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   15314          12 :                    .ToLocalChecked();
   15315           6 :   const char* expected_properties4_1[] = {"a", "b", nullptr};
   15316           6 :   CheckStringArray(isolate, properties, 3, expected_properties4_1);
   15317          12 :   CheckIsSymbolAt(isolate, properties, 2, "symbol");
   15318           6 : }
   15319             : 
   15320       23724 : THREADED_TEST(AccessChecksReenabledCorrectly) {
   15321           6 :   LocalContext context;
   15322           6 :   v8::Isolate* isolate = context->GetIsolate();
   15323          12 :   v8::HandleScope scope(isolate);
   15324           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   15325           6 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15326          18 :   templ->Set(v8_str("a"), v8_str("a"));
   15327             :   // Add more than 8 (see kMaxFastProperties) properties
   15328             :   // so that the constructor will force copying map.
   15329             :   // Cannot sprintf, gcc complains unsafety.
   15330             :   char buf[4];
   15331          66 :   for (char i = '0'; i <= '9' ; i++) {
   15332          60 :     buf[0] = i;
   15333         660 :     for (char j = '0'; j <= '9'; j++) {
   15334         600 :       buf[1] = j;
   15335        6600 :       for (char k = '0'; k <= '9'; k++) {
   15336        6000 :         buf[2] = k;
   15337        6000 :         buf[3] = 0;
   15338       18000 :         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   15339             :       }
   15340             :     }
   15341             :   }
   15342             : 
   15343             :   Local<v8::Object> instance_1 =
   15344           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   15345          30 :   CHECK(context->Global()
   15346             :             ->Set(context.local(), v8_str("obj_1"), instance_1)
   15347             :             .FromJust());
   15348             : 
   15349             :   Local<Value> value_1 = CompileRun("obj_1.a");
   15350           6 :   CHECK(value_1.IsEmpty());
   15351             : 
   15352             :   Local<v8::Object> instance_2 =
   15353           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   15354          30 :   CHECK(context->Global()
   15355             :             ->Set(context.local(), v8_str("obj_2"), instance_2)
   15356             :             .FromJust());
   15357             : 
   15358             :   Local<Value> value_2 = CompileRun("obj_2.a");
   15359          12 :   CHECK(value_2.IsEmpty());
   15360           6 : }
   15361             : 
   15362             : 
   15363             : // Tests that ScriptData can be serialized and deserialized.
   15364       23723 : TEST(PreCompileSerialization) {
   15365             :   // Producing cached parser data while parsing eagerly is not supported.
   15366           5 :   if (!i::FLAG_lazy) return;
   15367             : 
   15368           5 :   v8::V8::Initialize();
   15369           5 :   LocalContext env;
   15370           5 :   v8::Isolate* isolate = env->GetIsolate();
   15371          10 :   HandleScope handle_scope(isolate);
   15372             : 
   15373             :   const char* script = "function foo(a) { return a+1; }";
   15374           5 :   v8::ScriptCompiler::Source source(v8_str(script));
   15375             :   v8::ScriptCompiler::Compile(env.local(), &source,
   15376           5 :                               v8::ScriptCompiler::kProduceParserCache)
   15377           5 :       .ToLocalChecked();
   15378             :   // Serialize.
   15379           5 :   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
   15380           5 :   i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
   15381           5 :   i::MemCopy(serialized_data, cd->data, cd->length);
   15382             : 
   15383             :   // Deserialize.
   15384          10 :   i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
   15385             : 
   15386             :   // Verify that the original is the same as the deserialized.
   15387           5 :   CHECK_EQ(cd->length, deserialized->length());
   15388          10 :   CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
   15389             : 
   15390          10 :   delete deserialized;
   15391           5 :   i::DeleteArray(serialized_data);
   15392             : }
   15393             : 
   15394             : 
   15395             : // This tests that we do not allow dictionary load/call inline caches
   15396             : // to use functions that have not yet been compiled.  The potential
   15397             : // problem of loading a function that has not yet been compiled can
   15398             : // arise because we share code between contexts via the compilation
   15399             : // cache.
   15400       23724 : THREADED_TEST(DictionaryICLoadedFunction) {
   15401           6 :   v8::HandleScope scope(CcTest::isolate());
   15402             :   // Test LoadIC.
   15403          18 :   for (int i = 0; i < 2; i++) {
   15404          12 :     LocalContext context;
   15405          72 :     CHECK(context->Global()
   15406             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   15407             :               .FromJust());
   15408          60 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   15409             :     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   15410          12 :   }
   15411             :   // Test CallIC.
   15412          12 :   for (int i = 0; i < 2; i++) {
   15413          12 :     LocalContext context;
   15414          72 :     CHECK(context->Global()
   15415             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   15416             :               .FromJust());
   15417          60 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   15418             :     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   15419          18 :   }
   15420           6 : }
   15421             : 
   15422             : 
   15423             : // Test that cross-context new calls use the context of the callee to
   15424             : // create the new JavaScript object.
   15425       23724 : THREADED_TEST(CrossContextNew) {
   15426           6 :   v8::Isolate* isolate = CcTest::isolate();
   15427           6 :   v8::HandleScope scope(isolate);
   15428           6 :   v8::Local<Context> context0 = Context::New(isolate);
   15429           6 :   v8::Local<Context> context1 = Context::New(isolate);
   15430             : 
   15431             :   // Allow cross-domain access.
   15432           6 :   Local<String> token = v8_str("<security token>");
   15433           6 :   context0->SetSecurityToken(token);
   15434           6 :   context1->SetSecurityToken(token);
   15435             : 
   15436             :   // Set an 'x' property on the Object prototype and define a
   15437             :   // constructor function in context0.
   15438           6 :   context0->Enter();
   15439             :   CompileRun("Object.prototype.x = 42; function C() {};");
   15440           6 :   context0->Exit();
   15441             : 
   15442             :   // Call the constructor function from context0 and check that the
   15443             :   // result has the 'x' property.
   15444           6 :   context1->Enter();
   15445          30 :   CHECK(context1->Global()
   15446             :             ->Set(context1, v8_str("other"), context0->Global())
   15447             :             .FromJust());
   15448             :   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   15449           6 :   CHECK(value->IsInt32());
   15450          12 :   CHECK_EQ(42, value->Int32Value(context1).FromJust());
   15451           6 :   context1->Exit();
   15452           6 : }
   15453             : 
   15454             : 
   15455             : // Verify that we can clone an object
   15456       23723 : TEST(ObjectClone) {
   15457           5 :   LocalContext env;
   15458           5 :   v8::Isolate* isolate = env->GetIsolate();
   15459          10 :   v8::HandleScope scope(isolate);
   15460             : 
   15461             :   const char* sample =
   15462             :     "var rv = {};"      \
   15463             :     "rv.alpha = 'hello';" \
   15464             :     "rv.beta = 123;"     \
   15465             :     "rv;";
   15466             : 
   15467             :   // Create an object, verify basics.
   15468             :   Local<Value> val = CompileRun(sample);
   15469           5 :   CHECK(val->IsObject());
   15470             :   Local<v8::Object> obj = val.As<v8::Object>();
   15471          20 :   obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
   15472             : 
   15473          25 :   CHECK(v8_str("hello")
   15474             :             ->Equals(env.local(),
   15475             :                      obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   15476             :             .FromJust());
   15477          25 :   CHECK(v8::Integer::New(isolate, 123)
   15478             :             ->Equals(env.local(),
   15479             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15480             :             .FromJust());
   15481          25 :   CHECK(v8_str("cloneme")
   15482             :             ->Equals(env.local(),
   15483             :                      obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   15484             :             .FromJust());
   15485             : 
   15486             :   // Clone it.
   15487           5 :   Local<v8::Object> clone = obj->Clone();
   15488          25 :   CHECK(v8_str("hello")
   15489             :             ->Equals(env.local(),
   15490             :                      clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   15491             :             .FromJust());
   15492          25 :   CHECK(v8::Integer::New(isolate, 123)
   15493             :             ->Equals(env.local(),
   15494             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15495             :             .FromJust());
   15496          25 :   CHECK(v8_str("cloneme")
   15497             :             ->Equals(env.local(),
   15498             :                      clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   15499             :             .FromJust());
   15500             : 
   15501             :   // Set a property on the clone, verify each object.
   15502          20 :   CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
   15503             :             .FromJust());
   15504          25 :   CHECK(v8::Integer::New(isolate, 123)
   15505             :             ->Equals(env.local(),
   15506             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15507             :             .FromJust());
   15508          25 :   CHECK(v8::Integer::New(isolate, 456)
   15509             :             ->Equals(env.local(),
   15510             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15511           5 :             .FromJust());
   15512           5 : }
   15513             : 
   15514             : 
   15515             : class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   15516             :  public:
   15517             :   explicit OneByteVectorResource(i::Vector<const char> vector)
   15518           6 :       : data_(vector) {}
   15519           6 :   virtual ~OneByteVectorResource() {}
   15520          24 :   virtual size_t length() const { return data_.length(); }
   15521          24 :   virtual const char* data() const { return data_.start(); }
   15522             :  private:
   15523             :   i::Vector<const char> data_;
   15524             : };
   15525             : 
   15526             : 
   15527             : class UC16VectorResource : public v8::String::ExternalStringResource {
   15528             :  public:
   15529             :   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   15530          11 :       : data_(vector) {}
   15531           6 :   virtual ~UC16VectorResource() {}
   15532           0 :   virtual size_t length() const { return data_.length(); }
   15533         438 :   virtual const i::uc16* data() const { return data_.start(); }
   15534             :  private:
   15535             :   i::Vector<const i::uc16> data_;
   15536             : };
   15537             : 
   15538             : 
   15539          12 : static void MorphAString(i::String* string,
   15540             :                          OneByteVectorResource* one_byte_resource,
   15541             :                          UC16VectorResource* uc16_resource) {
   15542          12 :   CHECK(i::StringShape(string).IsExternal());
   15543          12 :   if (string->IsOneByteRepresentation()) {
   15544             :     // Check old map is not internalized or long.
   15545          12 :     CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
   15546             :     // Morph external string to be TwoByte string.
   15547          12 :     string->set_map(CcTest::heap()->external_string_map());
   15548             :     i::ExternalTwoByteString* morphed =
   15549             :          i::ExternalTwoByteString::cast(string);
   15550             :     morphed->set_resource(uc16_resource);
   15551             :   } else {
   15552             :     // Check old map is not internalized or long.
   15553           0 :     CHECK(string->map() == CcTest::heap()->external_string_map());
   15554             :     // Morph external string to be one-byte string.
   15555           0 :     string->set_map(CcTest::heap()->external_one_byte_string_map());
   15556             :     i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
   15557             :     morphed->set_resource(one_byte_resource);
   15558             :   }
   15559          12 : }
   15560             : 
   15561             : 
   15562             : // Test that we can still flatten a string if the components it is built up
   15563             : // from have been turned into 16 bit strings in the mean time.
   15564       23724 : THREADED_TEST(MorphCompositeStringTest) {
   15565             :   char utf_buffer[129];
   15566             :   const char* c_string = "Now is the time for all good men"
   15567             :                          " to come to the aid of the party";
   15568           6 :   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   15569             :   {
   15570           6 :     LocalContext env;
   15571             :     i::Factory* factory = CcTest::i_isolate()->factory();
   15572          12 :     v8::HandleScope scope(env->GetIsolate());
   15573             :     OneByteVectorResource one_byte_resource(
   15574             :         i::Vector<const char>(c_string, i::StrLength(c_string)));
   15575             :     UC16VectorResource uc16_resource(
   15576             :         i::Vector<const uint16_t>(two_byte_string,
   15577             :                                   i::StrLength(c_string)));
   15578             : 
   15579             :     Local<String> lhs(
   15580             :         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   15581          12 :                                         &one_byte_resource).ToHandleChecked()));
   15582             :     Local<String> rhs(
   15583             :         v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
   15584          12 :                                         &one_byte_resource).ToHandleChecked()));
   15585             : 
   15586          30 :     CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
   15587          30 :     CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
   15588             : 
   15589             :     CompileRun(
   15590             :         "var cons = lhs + rhs;"
   15591             :         "var slice = lhs.substring(1, lhs.length - 1);"
   15592             :         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   15593             : 
   15594           6 :     CHECK(lhs->IsOneByte());
   15595           6 :     CHECK(rhs->IsOneByte());
   15596             : 
   15597             :     MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
   15598           6 :                  &uc16_resource);
   15599             :     MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
   15600           6 :                  &uc16_resource);
   15601             : 
   15602             :     // This should UTF-8 without flattening, since everything is ASCII.
   15603             :     Local<String> cons =
   15604          12 :         v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
   15605           6 :     CHECK_EQ(128, cons->Utf8Length());
   15606           6 :     int nchars = -1;
   15607           6 :     CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
   15608           6 :     CHECK_EQ(128, nchars);
   15609           6 :     CHECK_EQ(0, strcmp(
   15610             :         utf_buffer,
   15611             :         "Now is the time for all good men to come to the aid of the party"
   15612             :         "Now is the time for all good men to come to the aid of the party"));
   15613             : 
   15614             :     // Now do some stuff to make sure the strings are flattened, etc.
   15615             :     CompileRun(
   15616             :         "/[^a-z]/.test(cons);"
   15617             :         "/[^a-z]/.test(slice);"
   15618             :         "/[^a-z]/.test(slice_on_cons);");
   15619             :     const char* expected_cons =
   15620             :         "Now is the time for all good men to come to the aid of the party"
   15621             :         "Now is the time for all good men to come to the aid of the party";
   15622             :     const char* expected_slice =
   15623             :         "ow is the time for all good men to come to the aid of the part";
   15624             :     const char* expected_slice_on_cons =
   15625             :         "ow is the time for all good men to come to the aid of the party"
   15626             :         "Now is the time for all good men to come to the aid of the part";
   15627          42 :     CHECK(v8_str(expected_cons)
   15628             :               ->Equals(env.local(), env->Global()
   15629             :                                         ->Get(env.local(), v8_str("cons"))
   15630             :                                         .ToLocalChecked())
   15631             :               .FromJust());
   15632          42 :     CHECK(v8_str(expected_slice)
   15633             :               ->Equals(env.local(), env->Global()
   15634             :                                         ->Get(env.local(), v8_str("slice"))
   15635             :                                         .ToLocalChecked())
   15636             :               .FromJust());
   15637          42 :     CHECK(v8_str(expected_slice_on_cons)
   15638             :               ->Equals(env.local(),
   15639             :                        env->Global()
   15640             :                            ->Get(env.local(), v8_str("slice_on_cons"))
   15641             :                            .ToLocalChecked())
   15642           6 :               .FromJust());
   15643             :   }
   15644             :   i::DeleteArray(two_byte_string);
   15645           6 : }
   15646             : 
   15647             : 
   15648       23723 : TEST(CompileExternalTwoByteSource) {
   15649           5 :   LocalContext context;
   15650          10 :   v8::HandleScope scope(context->GetIsolate());
   15651             : 
   15652             :   // This is a very short list of sources, which currently is to check for a
   15653             :   // regression caused by r2703.
   15654             :   const char* one_byte_sources[] = {
   15655             :       "0.5",
   15656             :       "-0.5",   // This mainly testes PushBack in the Scanner.
   15657             :       "--0.5",  // This mainly testes PushBack in the Scanner.
   15658           5 :       nullptr};
   15659             : 
   15660             :   // Compile the sources as external two byte strings.
   15661          20 :   for (int i = 0; one_byte_sources[i] != nullptr; i++) {
   15662          15 :     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15663          15 :     TestResource* uc16_resource = new TestResource(two_byte_string);
   15664             :     v8::Local<v8::String> source =
   15665          15 :         v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
   15666          30 :             .ToLocalChecked();
   15667          15 :     v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
   15668           5 :   }
   15669           5 : }
   15670             : 
   15671             : 
   15672             : #ifndef V8_INTERPRETED_REGEXP
   15673             : 
   15674       23718 : struct RegExpInterruptionData {
   15675             :   v8::base::Atomic32 loop_count;
   15676             :   UC16VectorResource* string_resource;
   15677             :   v8::Persistent<v8::String> string;
   15678       23718 : } regexp_interruption_data;
   15679             : 
   15680             : 
   15681           5 : class RegExpInterruptionThread : public v8::base::Thread {
   15682             :  public:
   15683             :   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   15684           5 :       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
   15685             : 
   15686           5 :   virtual void Run() {
   15687          40 :     for (v8::base::Relaxed_Store(&regexp_interruption_data.loop_count, 0);
   15688             :          v8::base::Relaxed_Load(&regexp_interruption_data.loop_count) < 7;
   15689             :          v8::base::Relaxed_AtomicIncrement(&regexp_interruption_data.loop_count,
   15690             :                                            1)) {
   15691             :       // Wait a bit before requesting GC.
   15692          35 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15693          35 :       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   15694             :     }
   15695             :     // Wait a bit before terminating.
   15696           5 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15697           5 :     isolate_->TerminateExecution();
   15698           5 :   }
   15699             : 
   15700             :  private:
   15701             :   v8::Isolate* isolate_;
   15702             : };
   15703             : 
   15704             : 
   15705           2 : void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
   15706             :                  v8::GCCallbackFlags flags) {
   15707           2 :   if (v8::base::Relaxed_Load(&regexp_interruption_data.loop_count) != 2) {
   15708           2 :     return;
   15709             :   }
   15710           0 :   v8::HandleScope scope(isolate);
   15711             :   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   15712           0 :       CcTest::isolate(), regexp_interruption_data.string);
   15713           0 :   string->MakeExternal(regexp_interruption_data.string_resource);
   15714             : }
   15715             : 
   15716             : 
   15717             : // Test that RegExp execution can be interrupted.  Specifically, we test
   15718             : // * interrupting with GC
   15719             : // * turn the subject string from one-byte internal to two-byte external string
   15720             : // * force termination
   15721       23723 : TEST(RegExpInterruption) {
   15722           5 :   LocalContext env;
   15723          10 :   v8::HandleScope scope(env->GetIsolate());
   15724             : 
   15725           5 :   RegExpInterruptionThread timeout_thread(env->GetIsolate());
   15726             : 
   15727           5 :   env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
   15728             :   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   15729           5 :   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
   15730           5 :   v8::Local<v8::String> string = v8_str(one_byte_content);
   15731             : 
   15732          25 :   env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
   15733           5 :   regexp_interruption_data.string.Reset(env->GetIsolate(), string);
   15734             :   regexp_interruption_data.string_resource = new UC16VectorResource(
   15735          15 :       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
   15736             : 
   15737          10 :   v8::TryCatch try_catch(env->GetIsolate());
   15738           5 :   timeout_thread.Start();
   15739             : 
   15740             :   CompileRun("/((a*)*)*b/.exec(a)");
   15741           5 :   CHECK(try_catch.HasTerminated());
   15742             : 
   15743           5 :   timeout_thread.Join();
   15744             : 
   15745             :   regexp_interruption_data.string.Reset();
   15746           5 :   i::DeleteArray(uc16_content);
   15747           5 : }
   15748             : 
   15749             : #endif  // V8_INTERPRETED_REGEXP
   15750             : 
   15751             : 
   15752             : // Test that we cannot set a property on the global object if there
   15753             : // is a read-only property in the prototype chain.
   15754       23723 : TEST(ReadOnlyPropertyInGlobalProto) {
   15755           5 :   v8::Isolate* isolate = CcTest::isolate();
   15756           5 :   v8::HandleScope scope(isolate);
   15757           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15758          10 :   LocalContext context(0, templ);
   15759           5 :   v8::Local<v8::Object> global = context->Global();
   15760             :   v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
   15761          20 :       global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
   15762             :   global_proto->DefineOwnProperty(context.local(), v8_str("x"),
   15763          20 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15764          10 :       .FromJust();
   15765             :   global_proto->DefineOwnProperty(context.local(), v8_str("y"),
   15766          20 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15767          10 :       .FromJust();
   15768             :   // Check without 'eval' or 'with'.
   15769             :   v8::Local<v8::Value> res =
   15770           5 :       CompileRun("function f() { x = 42; return x; }; f()");
   15771          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15772             :   // Check with 'eval'.
   15773           5 :   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15774          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15775             :   // Check with 'with'.
   15776           5 :   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15777          20 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15778           5 : }
   15779             : 
   15780             : 
   15781       23723 : TEST(CreateDataProperty) {
   15782           5 :   LocalContext env;
   15783           5 :   v8::Isolate* isolate = env->GetIsolate();
   15784          10 :   v8::HandleScope handle_scope(isolate);
   15785             : 
   15786             :   CompileRun(
   15787             :       "var a = {};"
   15788             :       "var b = [];"
   15789             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15790             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15791             : 
   15792             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15793          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15794             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15795          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15796             :   {
   15797             :     // Can't change a non-configurable properties.
   15798           5 :     v8::TryCatch try_catch(isolate);
   15799          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
   15800             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15801           5 :     CHECK(!try_catch.HasCaught());
   15802          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
   15803             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15804           5 :     CHECK(!try_catch.HasCaught());
   15805             :     v8::Local<v8::Value> val =
   15806          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15807           5 :     CHECK(val->IsNumber());
   15808          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15809             :   }
   15810             : 
   15811             :   {
   15812             :     // Set a regular property.
   15813           5 :     v8::TryCatch try_catch(isolate);
   15814          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
   15815             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15816           5 :     CHECK(!try_catch.HasCaught());
   15817             :     v8::Local<v8::Value> val =
   15818          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15819           5 :     CHECK(val->IsNumber());
   15820          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15821             :   }
   15822             : 
   15823             :   {
   15824             :     // Set an indexed property.
   15825           5 :     v8::TryCatch try_catch(isolate);
   15826          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
   15827             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15828           5 :     CHECK(!try_catch.HasCaught());
   15829           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15830           5 :     CHECK(val->IsNumber());
   15831          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15832             :   }
   15833             : 
   15834             :   {
   15835             :     // Special cases for arrays.
   15836           5 :     v8::TryCatch try_catch(isolate);
   15837          20 :     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
   15838             :                                    v8::Integer::New(isolate, 1)).FromJust());
   15839           5 :     CHECK(!try_catch.HasCaught());
   15840             :   }
   15841             :   {
   15842             :     // Special cases for arrays: index exceeds the array's length
   15843           5 :     v8::TryCatch try_catch(isolate);
   15844          15 :     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
   15845             :               .FromJust());
   15846           5 :     CHECK(!try_catch.HasCaught());
   15847           5 :     CHECK_EQ(2U, arr->Length());
   15848           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15849           5 :     CHECK(val->IsNumber());
   15850          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15851             : 
   15852             :     // Set an existing entry.
   15853          15 :     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
   15854             :               .FromJust());
   15855           5 :     CHECK(!try_catch.HasCaught());
   15856           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15857           5 :     CHECK(val->IsNumber());
   15858          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15859             :   }
   15860             : 
   15861             :   CompileRun("Object.freeze(a);");
   15862             :   {
   15863             :     // Can't change non-extensible objects.
   15864           5 :     v8::TryCatch try_catch(isolate);
   15865          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
   15866             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15867           5 :     CHECK(!try_catch.HasCaught());
   15868             :   }
   15869             : 
   15870           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15871           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15872             :   v8::Local<v8::Object> access_checked =
   15873           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15874             :   {
   15875           5 :     v8::TryCatch try_catch(isolate);
   15876          20 :     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
   15877             :                                              v8::Integer::New(isolate, 42))
   15878             :               .IsNothing());
   15879           5 :     CHECK(try_catch.HasCaught());
   15880           5 :   }
   15881           5 : }
   15882             : 
   15883             : 
   15884       23723 : TEST(DefineOwnProperty) {
   15885           5 :   LocalContext env;
   15886           5 :   v8::Isolate* isolate = env->GetIsolate();
   15887          10 :   v8::HandleScope handle_scope(isolate);
   15888             : 
   15889             :   CompileRun(
   15890             :       "var a = {};"
   15891             :       "var b = [];"
   15892             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15893             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15894             : 
   15895             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15896          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15897             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15898          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15899             :   {
   15900             :     // Can't change a non-configurable properties.
   15901           5 :     v8::TryCatch try_catch(isolate);
   15902          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
   15903             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15904           5 :     CHECK(!try_catch.HasCaught());
   15905          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
   15906             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15907           5 :     CHECK(!try_catch.HasCaught());
   15908             :     v8::Local<v8::Value> val =
   15909          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15910           5 :     CHECK(val->IsNumber());
   15911          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15912             :   }
   15913             : 
   15914             :   {
   15915             :     // Set a regular property.
   15916           5 :     v8::TryCatch try_catch(isolate);
   15917          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
   15918             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15919           5 :     CHECK(!try_catch.HasCaught());
   15920             :     v8::Local<v8::Value> val =
   15921          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15922           5 :     CHECK(val->IsNumber());
   15923          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15924             :   }
   15925             : 
   15926             :   {
   15927             :     // Set an indexed property.
   15928           5 :     v8::TryCatch try_catch(isolate);
   15929          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
   15930             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15931           5 :     CHECK(!try_catch.HasCaught());
   15932           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15933           5 :     CHECK(val->IsNumber());
   15934          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15935             :   }
   15936             : 
   15937             :   {
   15938             :     // Special cases for arrays.
   15939           5 :     v8::TryCatch try_catch(isolate);
   15940          20 :     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
   15941             :                                   v8::Integer::New(isolate, 1)).FromJust());
   15942           5 :     CHECK(!try_catch.HasCaught());
   15943             :   }
   15944             :   {
   15945             :     // Special cases for arrays: index exceeds the array's length
   15946           5 :     v8::TryCatch try_catch(isolate);
   15947          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
   15948             :                                  v8::Integer::New(isolate, 23)).FromJust());
   15949           5 :     CHECK(!try_catch.HasCaught());
   15950           5 :     CHECK_EQ(2U, arr->Length());
   15951           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15952           5 :     CHECK(val->IsNumber());
   15953          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15954             : 
   15955             :     // Set an existing entry.
   15956          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
   15957             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15958           5 :     CHECK(!try_catch.HasCaught());
   15959           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15960           5 :     CHECK(val->IsNumber());
   15961          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15962             :   }
   15963             : 
   15964             :   {
   15965             :     // Set a non-writable property.
   15966           5 :     v8::TryCatch try_catch(isolate);
   15967          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
   15968             :                                  v8::Integer::New(isolate, 42),
   15969             :                                  v8::ReadOnly).FromJust());
   15970           5 :     CHECK(!try_catch.HasCaught());
   15971             :     v8::Local<v8::Value> val =
   15972          15 :         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
   15973           5 :     CHECK(val->IsNumber());
   15974          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15975          15 :     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
   15976             :                                     env.local(), v8_str("lala")).FromJust());
   15977           5 :     CHECK(!try_catch.HasCaught());
   15978             :   }
   15979             : 
   15980             :   CompileRun("Object.freeze(a);");
   15981             :   {
   15982             :     // Can't change non-extensible objects.
   15983           5 :     v8::TryCatch try_catch(isolate);
   15984          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
   15985             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15986           5 :     CHECK(!try_catch.HasCaught());
   15987             :   }
   15988             : 
   15989           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15990           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15991             :   v8::Local<v8::Object> access_checked =
   15992           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15993             :   {
   15994           5 :     v8::TryCatch try_catch(isolate);
   15995          20 :     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
   15996             :                                             v8::Integer::New(isolate, 42))
   15997             :               .IsNothing());
   15998           5 :     CHECK(try_catch.HasCaught());
   15999           5 :   }
   16000           5 : }
   16001             : 
   16002       23723 : TEST(DefineProperty) {
   16003           5 :   LocalContext env;
   16004           5 :   v8::Isolate* isolate = env->GetIsolate();
   16005          10 :   v8::HandleScope handle_scope(isolate);
   16006             : 
   16007             :   v8::Local<v8::Name> p;
   16008             : 
   16009             :   CompileRun(
   16010             :       "var a = {};"
   16011             :       "var b = [];"
   16012             :       "Object.defineProperty(a, 'v1', {value: 23});"
   16013             :       "Object.defineProperty(a, 'v2', {value: 23, configurable: true});");
   16014             : 
   16015             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   16016          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   16017             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   16018          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   16019             : 
   16020          10 :   v8::PropertyDescriptor desc(v8_num(42));
   16021             :   {
   16022             :     // Use a data descriptor.
   16023             : 
   16024             :     // Cannot change a non-configurable property.
   16025           5 :     p = v8_str("v1");
   16026           5 :     v8::TryCatch try_catch(isolate);
   16027          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc).FromJust());
   16028           5 :     CHECK(!try_catch.HasCaught());
   16029          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16030           5 :     CHECK(val->IsNumber());
   16031          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   16032             : 
   16033             :     // Change a configurable property.
   16034           5 :     p = v8_str("v2");
   16035          10 :     obj->DefineProperty(env.local(), p, desc).FromJust();
   16036          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16037           5 :     CHECK(!try_catch.HasCaught());
   16038          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16039           5 :     CHECK(val->IsNumber());
   16040          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16041             : 
   16042             :     // Check that missing writable has default value false.
   16043           5 :     p = v8_str("v12");
   16044          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16045           5 :     CHECK(!try_catch.HasCaught());
   16046          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16047           5 :     CHECK(val->IsNumber());
   16048          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16049          10 :     v8::PropertyDescriptor desc2(v8_num(43));
   16050          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc2).FromJust());
   16051          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16052          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16053          10 :     CHECK(!try_catch.HasCaught());
   16054             :   }
   16055             : 
   16056             :   {
   16057             :     // Set a regular property.
   16058           5 :     p = v8_str("v3");
   16059           5 :     v8::TryCatch try_catch(isolate);
   16060          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16061           5 :     CHECK(!try_catch.HasCaught());
   16062          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16063           5 :     CHECK(val->IsNumber());
   16064          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16065             :   }
   16066             : 
   16067             :   {
   16068             :     // Set an indexed property.
   16069           5 :     v8::TryCatch try_catch(isolate);
   16070          15 :     CHECK(obj->DefineProperty(env.local(), v8_str("1"), desc).FromJust());
   16071           5 :     CHECK(!try_catch.HasCaught());
   16072           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   16073           5 :     CHECK(val->IsNumber());
   16074          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16075             :   }
   16076             : 
   16077             :   {
   16078             :     // No special case when changing array length.
   16079           5 :     v8::TryCatch try_catch(isolate);
   16080             :     // Use a writable descriptor, otherwise the next test, that changes
   16081             :     // the array length will fail.
   16082          10 :     v8::PropertyDescriptor desc(v8_num(42), true);
   16083          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("length"), desc).FromJust());
   16084          10 :     CHECK(!try_catch.HasCaught());
   16085             :   }
   16086             : 
   16087             :   {
   16088             :     // Special cases for arrays: index exceeds the array's length.
   16089           5 :     v8::TryCatch try_catch(isolate);
   16090          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("100"), desc).FromJust());
   16091           5 :     CHECK(!try_catch.HasCaught());
   16092           5 :     CHECK_EQ(101U, arr->Length());
   16093           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 100).ToLocalChecked();
   16094           5 :     CHECK(val->IsNumber());
   16095          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16096             : 
   16097             :     // Set an existing entry.
   16098          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("0"), desc).FromJust());
   16099           5 :     CHECK(!try_catch.HasCaught());
   16100           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   16101           5 :     CHECK(val->IsNumber());
   16102          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16103             :   }
   16104             : 
   16105             :   {
   16106             :     // Use a generic descriptor.
   16107           5 :     v8::PropertyDescriptor desc_generic;
   16108             : 
   16109           5 :     p = v8_str("v4");
   16110          10 :     v8::TryCatch try_catch(isolate);
   16111          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_generic).FromJust());
   16112           5 :     CHECK(!try_catch.HasCaught());
   16113          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16114           5 :     CHECK(val->IsUndefined());
   16115             : 
   16116          15 :     obj->Set(env.local(), p, v8_num(1)).FromJust();
   16117           5 :     CHECK(!try_catch.HasCaught());
   16118             : 
   16119          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16120           5 :     CHECK(val->IsUndefined());
   16121          10 :     CHECK(!try_catch.HasCaught());
   16122             :   }
   16123             : 
   16124             :   {
   16125             :     // Use a data descriptor with undefined value.
   16126           5 :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate));
   16127             : 
   16128          10 :     v8::TryCatch try_catch(isolate);
   16129          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16130           5 :     CHECK(!try_catch.HasCaught());
   16131          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16132           5 :     CHECK(val->IsUndefined());
   16133          10 :     CHECK(!try_catch.HasCaught());
   16134             :   }
   16135             : 
   16136             :   {
   16137             :     // Use a descriptor with attribute == v8::ReadOnly.
   16138           5 :     v8::PropertyDescriptor desc_read_only(v8_num(42), false);
   16139           5 :     desc_read_only.set_enumerable(true);
   16140           5 :     desc_read_only.set_configurable(true);
   16141             : 
   16142           5 :     p = v8_str("v5");
   16143          10 :     v8::TryCatch try_catch(isolate);
   16144          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_read_only).FromJust());
   16145           5 :     CHECK(!try_catch.HasCaught());
   16146          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16147           5 :     CHECK(val->IsNumber());
   16148          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16149          10 :     CHECK_EQ(v8::ReadOnly,
   16150             :              obj->GetPropertyAttributes(env.local(), p).FromJust());
   16151          10 :     CHECK(!try_catch.HasCaught());
   16152             :   }
   16153             : 
   16154             :   {
   16155             :     // Use an accessor descriptor with empty handles.
   16156             :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate),
   16157           5 :                                       v8::Undefined(isolate));
   16158             : 
   16159           5 :     p = v8_str("v6");
   16160          10 :     v8::TryCatch try_catch(isolate);
   16161          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16162           5 :     CHECK(!try_catch.HasCaught());
   16163          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16164           5 :     CHECK(val->IsUndefined());
   16165          10 :     CHECK(!try_catch.HasCaught());
   16166             :   }
   16167             : 
   16168             :   {
   16169             :     // Use an accessor descriptor.
   16170             :     CompileRun(
   16171             :         "var set = function(x) {this.val = 2*x;};"
   16172             :         "var get = function() {return this.val || 0;};");
   16173             : 
   16174             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   16175          25 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   16176             :     v8::Local<v8::Function> set = v8::Local<v8::Function>::Cast(
   16177          25 :         env->Global()->Get(env.local(), v8_str("set")).ToLocalChecked());
   16178           5 :     v8::PropertyDescriptor desc(get, set);
   16179             : 
   16180           5 :     p = v8_str("v7");
   16181          10 :     v8::TryCatch try_catch(isolate);
   16182          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16183           5 :     CHECK(!try_catch.HasCaught());
   16184             : 
   16185          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16186           5 :     CHECK(val->IsNumber());
   16187          10 :     CHECK_EQ(0.0, val->NumberValue(env.local()).FromJust());
   16188           5 :     CHECK(!try_catch.HasCaught());
   16189             : 
   16190          15 :     obj->Set(env.local(), p, v8_num(7)).FromJust();
   16191           5 :     CHECK(!try_catch.HasCaught());
   16192             : 
   16193          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16194           5 :     CHECK(val->IsNumber());
   16195          10 :     CHECK_EQ(14.0, val->NumberValue(env.local()).FromJust());
   16196          10 :     CHECK(!try_catch.HasCaught());
   16197             :   }
   16198             : 
   16199             :   {
   16200             :     // Redefine an existing property.
   16201             : 
   16202             :     // desc = {value: 42, enumerable: true}
   16203           5 :     v8::PropertyDescriptor desc(v8_num(42));
   16204           5 :     desc.set_enumerable(true);
   16205             : 
   16206           5 :     p = v8_str("v8");
   16207          10 :     v8::TryCatch try_catch(isolate);
   16208          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16209           5 :     CHECK(!try_catch.HasCaught());
   16210             : 
   16211             :     // desc = {enumerable: true}
   16212          10 :     v8::PropertyDescriptor desc_true((v8::Local<v8::Value>()));
   16213           5 :     desc_true.set_enumerable(true);
   16214             : 
   16215             :     // Successful redefinition because all present attributes have the same
   16216             :     // value as the current descriptor.
   16217          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_true).FromJust());
   16218           5 :     CHECK(!try_catch.HasCaught());
   16219             : 
   16220             :     // desc = {}
   16221          10 :     v8::PropertyDescriptor desc_empty;
   16222             :     // Successful redefinition because no attributes are overwritten in the
   16223             :     // current descriptor.
   16224          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16225           5 :     CHECK(!try_catch.HasCaught());
   16226             : 
   16227             :     // desc = {enumerable: false}
   16228          10 :     v8::PropertyDescriptor desc_false((v8::Local<v8::Value>()));
   16229           5 :     desc_false.set_enumerable(false);
   16230             :     // Not successful because we cannot define a different value for enumerable.
   16231          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_false).FromJust());
   16232          10 :     CHECK(!try_catch.HasCaught());
   16233             :   }
   16234             : 
   16235             :   {
   16236             :     // Redefine a property that has a getter.
   16237             :     CompileRun("var get = function() {};");
   16238             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   16239          25 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   16240             : 
   16241             :     // desc = {get: function() {}}
   16242           5 :     v8::PropertyDescriptor desc(get, v8::Local<v8::Function>());
   16243          10 :     v8::TryCatch try_catch(isolate);
   16244             : 
   16245           5 :     p = v8_str("v9");
   16246          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16247           5 :     CHECK(!try_catch.HasCaught());
   16248             : 
   16249             :     // desc_empty = {}
   16250             :     // Successful because we are not redefining the current getter.
   16251          10 :     v8::PropertyDescriptor desc_empty;
   16252          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16253           5 :     CHECK(!try_catch.HasCaught());
   16254             : 
   16255             :     // desc = {get: function() {}}
   16256             :     // Successful because we redefine the getter with its current value.
   16257          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16258           5 :     CHECK(!try_catch.HasCaught());
   16259             : 
   16260             :     // desc = {get: undefined}
   16261             :     v8::PropertyDescriptor desc_undefined(v8::Undefined(isolate),
   16262          10 :                                           v8::Local<v8::Function>());
   16263             :     // Not successful because we cannot redefine with the current value of get
   16264             :     // with undefined.
   16265          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_undefined).FromJust());
   16266          10 :     CHECK(!try_catch.HasCaught());
   16267             :   }
   16268             : 
   16269             :   CompileRun("Object.freeze(a);");
   16270             :   {
   16271             :     // We cannot change non-extensible objects.
   16272           5 :     v8::TryCatch try_catch(isolate);
   16273          15 :     CHECK(!obj->DefineProperty(env.local(), v8_str("v10"), desc).FromJust());
   16274           5 :     CHECK(!try_catch.HasCaught());
   16275             :   }
   16276             : 
   16277           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   16278           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   16279             :   v8::Local<v8::Object> access_checked =
   16280           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   16281             :   {
   16282           5 :     v8::TryCatch try_catch(isolate);
   16283          15 :     CHECK(access_checked->DefineProperty(env.local(), v8_str("v11"), desc)
   16284             :               .IsNothing());
   16285           5 :     CHECK(try_catch.HasCaught());
   16286           5 :   }
   16287           5 : }
   16288             : 
   16289       23724 : THREADED_TEST(GetCurrentContextWhenNotInContext) {
   16290           6 :   i::Isolate* isolate = CcTest::i_isolate();
   16291           6 :   CHECK_NOT_NULL(isolate);
   16292           6 :   CHECK_NULL(isolate->context());
   16293             :   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   16294           6 :   v8::HandleScope scope(v8_isolate);
   16295             :   // The following should not crash, but return an empty handle.
   16296           6 :   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   16297           6 :   CHECK(current.IsEmpty());
   16298           6 : }
   16299             : 
   16300             : 
   16301             : // Check that a variable declaration with no explicit initialization
   16302             : // value does shadow an existing property in the prototype chain.
   16303       23724 : THREADED_TEST(InitGlobalVarInProtoChain) {
   16304           6 :   LocalContext context;
   16305          12 :   v8::HandleScope scope(context->GetIsolate());
   16306             :   // Introduce a variable in the prototype chain.
   16307             :   CompileRun("__proto__.x = 42");
   16308             :   v8::Local<v8::Value> result = CompileRun("var x = 43; x");
   16309           6 :   CHECK(!result->IsUndefined());
   16310          18 :   CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
   16311           6 : }
   16312             : 
   16313             : 
   16314             : // Regression test for issue 398.
   16315             : // If a function is added to an object, creating a constant function
   16316             : // field, and the result is cloned, replacing the constant function on the
   16317             : // original should not affect the clone.
   16318             : // See http://code.google.com/p/v8/issues/detail?id=398
   16319       23724 : THREADED_TEST(ReplaceConstantFunction) {
   16320           6 :   LocalContext context;
   16321           6 :   v8::Isolate* isolate = context->GetIsolate();
   16322          12 :   v8::HandleScope scope(isolate);
   16323           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   16324             :   v8::Local<v8::FunctionTemplate> func_templ =
   16325           6 :       v8::FunctionTemplate::New(isolate);
   16326           6 :   v8::Local<v8::String> foo_string = v8_str("foo");
   16327             :   obj->Set(context.local(), foo_string,
   16328          24 :            func_templ->GetFunction(context.local()).ToLocalChecked())
   16329          12 :       .FromJust();
   16330           6 :   v8::Local<v8::Object> obj_clone = obj->Clone();
   16331          24 :   obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
   16332          18 :   CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
   16333           6 : }
   16334             : 
   16335             : 
   16336         504 : static void CheckElementValue(i::Isolate* isolate,
   16337             :                               int expected,
   16338             :                               i::Handle<i::Object> obj,
   16339             :                               int offset) {
   16340             :   i::Object* element =
   16341        1008 :       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   16342         504 :   CHECK_EQ(expected, i::Smi::ToInt(element));
   16343         504 : }
   16344             : 
   16345             : 
   16346             : template <class ExternalArrayClass, class ElementType>
   16347         162 : static void ObjectWithExternalArrayTestHelper(Local<Context> context,
   16348             :                                               v8::Local<Object> obj,
   16349             :                                               int element_count,
   16350             :                                               i::ExternalArrayType array_type,
   16351             :                                               int64_t low, int64_t high) {
   16352             :   i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
   16353             :   i::Isolate* isolate = jsobj->GetIsolate();
   16354             :   obj->Set(context, v8_str("field"),
   16355         486 :            v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
   16356         324 :       .FromJust();
   16357         648 :   CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
   16358             :   v8::Local<v8::Value> result = CompileRun("ext_array.field");
   16359         324 :   CHECK_EQ(1503, result->Int32Value(context).FromJust());
   16360             :   result = CompileRun("ext_array[1]");
   16361         324 :   CHECK_EQ(1, result->Int32Value(context).FromJust());
   16362             : 
   16363             :   // Check assigned smis
   16364             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16365             :                       "  ext_array[i] = i;"
   16366             :                       "}"
   16367             :                       "var sum = 0;"
   16368             :                       "for (var i = 0; i < 8; i++) {"
   16369             :                       "  sum += ext_array[i];"
   16370             :                       "}"
   16371             :                       "sum;");
   16372             : 
   16373         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16374             :   // Check pass through of assigned smis
   16375             :   result = CompileRun("var sum = 0;"
   16376             :                       "for (var i = 0; i < 8; i++) {"
   16377             :                       "  sum += ext_array[i] = ext_array[i] = -i;"
   16378             :                       "}"
   16379             :                       "sum;");
   16380         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   16381             : 
   16382             : 
   16383             :   // Check assigned smis in reverse order
   16384             :   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   16385             :                       "  ext_array[i] = i;"
   16386             :                       "}"
   16387             :                       "var sum = 0;"
   16388             :                       "for (var i = 0; i < 8; i++) {"
   16389             :                       "  sum += ext_array[i];"
   16390             :                       "}"
   16391             :                       "sum;");
   16392         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16393             : 
   16394             :   // Check pass through of assigned HeapNumbers
   16395             :   result = CompileRun("var sum = 0;"
   16396             :                       "for (var i = 0; i < 16; i+=2) {"
   16397             :                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   16398             :                       "}"
   16399             :                       "sum;");
   16400         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   16401             : 
   16402             :   // Check assigned HeapNumbers
   16403             :   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   16404             :                       "  ext_array[i] = (i * 0.5);"
   16405             :                       "}"
   16406             :                       "var sum = 0;"
   16407             :                       "for (var i = 0; i < 16; i+=2) {"
   16408             :                       "  sum += ext_array[i];"
   16409             :                       "}"
   16410             :                       "sum;");
   16411         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16412             : 
   16413             :   // Check assigned HeapNumbers in reverse order
   16414             :   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   16415             :                       "  ext_array[i] = (i * 0.5);"
   16416             :                       "}"
   16417             :                       "var sum = 0;"
   16418             :                       "for (var i = 0; i < 16; i+=2) {"
   16419             :                       "  sum += ext_array[i];"
   16420             :                       "}"
   16421             :                       "sum;");
   16422         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16423             : 
   16424             :   i::ScopedVector<char> test_buf(1024);
   16425             : 
   16426             :   // Check legal boundary conditions.
   16427             :   // The repeated loads and stores ensure the ICs are exercised.
   16428             :   const char* boundary_program =
   16429             :       "var res = 0;"
   16430             :       "for (var i = 0; i < 16; i++) {"
   16431             :       "  ext_array[i] = %lld;"
   16432             :       "  if (i > 8) {"
   16433             :       "    res = ext_array[i];"
   16434             :       "  }"
   16435             :       "}"
   16436             :       "res;";
   16437         162 :   i::SNPrintF(test_buf,
   16438             :               boundary_program,
   16439             :               low);
   16440             :   result = CompileRun(test_buf.start());
   16441         324 :   CHECK_EQ(low, result->IntegerValue(context).FromJust());
   16442             : 
   16443         162 :   i::SNPrintF(test_buf,
   16444             :               boundary_program,
   16445             :               high);
   16446             :   result = CompileRun(test_buf.start());
   16447         324 :   CHECK_EQ(high, result->IntegerValue(context).FromJust());
   16448             : 
   16449             :   // Check misprediction of type in IC.
   16450             :   result = CompileRun("var tmp_array = ext_array;"
   16451             :                       "var sum = 0;"
   16452             :                       "for (var i = 0; i < 8; i++) {"
   16453             :                       "  tmp_array[i] = i;"
   16454             :                       "  sum += tmp_array[i];"
   16455             :                       "  if (i == 4) {"
   16456             :                       "    tmp_array = {};"
   16457             :                       "  }"
   16458             :                       "}"
   16459             :                       "sum;");
   16460             :   // Force GC to trigger verification.
   16461         162 :   CcTest::CollectAllGarbage();
   16462         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16463             : 
   16464             :   // Make sure out-of-range loads do not throw.
   16465         162 :   i::SNPrintF(test_buf,
   16466             :               "var caught_exception = false;"
   16467             :               "try {"
   16468             :               "  ext_array[%d];"
   16469             :               "} catch (e) {"
   16470             :               "  caught_exception = true;"
   16471             :               "}"
   16472             :               "caught_exception;",
   16473             :               element_count);
   16474             :   result = CompileRun(test_buf.start());
   16475         324 :   CHECK(!result->BooleanValue(context).FromJust());
   16476             : 
   16477             :   // Make sure out-of-range stores do not throw.
   16478         162 :   i::SNPrintF(test_buf,
   16479             :               "var caught_exception = false;"
   16480             :               "try {"
   16481             :               "  ext_array[%d] = 1;"
   16482             :               "} catch (e) {"
   16483             :               "  caught_exception = true;"
   16484             :               "}"
   16485             :               "caught_exception;",
   16486             :               element_count);
   16487             :   result = CompileRun(test_buf.start());
   16488         324 :   CHECK(!result->BooleanValue(context).FromJust());
   16489             : 
   16490             :   // Check other boundary conditions, values and operations.
   16491             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16492             :                       "  ext_array[7] = undefined;"
   16493             :                       "}"
   16494             :                       "ext_array[7];");
   16495         324 :   CHECK_EQ(0, result->Int32Value(context).FromJust());
   16496         162 :   if (array_type == i::kExternalFloat64Array ||
   16497             :       array_type == i::kExternalFloat32Array) {
   16498          72 :     CHECK(std::isnan(
   16499             :         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
   16500             :   } else {
   16501         126 :     CheckElementValue(isolate, 0, jsobj, 7);
   16502             :   }
   16503             : 
   16504             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16505             :                       "  ext_array[6] = '2.3';"
   16506             :                       "}"
   16507             :                       "ext_array[6];");
   16508         324 :   CHECK_EQ(2, result->Int32Value(context).FromJust());
   16509         324 :   CHECK_EQ(2,
   16510             :            static_cast<int>(
   16511             :                i::Object::GetElement(
   16512             :                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   16513             : 
   16514         162 :   if (array_type != i::kExternalFloat32Array &&
   16515             :       array_type != i::kExternalFloat64Array) {
   16516             :     // Though the specification doesn't state it, be explicit about
   16517             :     // converting NaNs and +/-Infinity to zero.
   16518             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16519             :                         "  ext_array[i] = 5;"
   16520             :                         "}"
   16521             :                         "for (var i = 0; i < 8; i++) {"
   16522             :                         "  ext_array[i] = NaN;"
   16523             :                         "}"
   16524             :                         "ext_array[5];");
   16525         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   16526         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   16527             : 
   16528             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16529             :                         "  ext_array[i] = 5;"
   16530             :                         "}"
   16531             :                         "for (var i = 0; i < 8; i++) {"
   16532             :                         "  ext_array[i] = Infinity;"
   16533             :                         "}"
   16534             :                         "ext_array[5];");
   16535             :     int expected_value =
   16536         126 :         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
   16537         252 :     CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
   16538         126 :     CheckElementValue(isolate, expected_value, jsobj, 5);
   16539             : 
   16540             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16541             :                         "  ext_array[i] = 5;"
   16542             :                         "}"
   16543             :                         "for (var i = 0; i < 8; i++) {"
   16544             :                         "  ext_array[i] = -Infinity;"
   16545             :                         "}"
   16546             :                         "ext_array[5];");
   16547         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   16548         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   16549             : 
   16550             :     // Check truncation behavior of integral arrays.
   16551             :     const char* unsigned_data =
   16552             :         "var source_data = [0.6, 10.6];"
   16553             :         "var expected_results = [0, 10];";
   16554             :     const char* signed_data =
   16555             :         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   16556             :         "var expected_results = [0, 10, 0, -10];";
   16557             :     const char* pixel_data =
   16558             :         "var source_data = [0.6, 10.6];"
   16559             :         "var expected_results = [1, 11];";
   16560             :     bool is_unsigned = (array_type == i::kExternalUint8Array ||
   16561             :                         array_type == i::kExternalUint16Array ||
   16562         126 :                         array_type == i::kExternalUint32Array);
   16563             :     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
   16564             : 
   16565         126 :     i::SNPrintF(test_buf,
   16566             :                 "%s"
   16567             :                 "var all_passed = true;"
   16568             :                 "for (var i = 0; i < source_data.length; i++) {"
   16569             :                 "  for (var j = 0; j < 8; j++) {"
   16570             :                 "    ext_array[j] = source_data[i];"
   16571             :                 "  }"
   16572             :                 "  all_passed = all_passed &&"
   16573             :                 "               (ext_array[5] == expected_results[i]);"
   16574             :                 "}"
   16575             :                 "all_passed;",
   16576             :                 (is_unsigned ?
   16577             :                      unsigned_data :
   16578         126 :                      (is_pixel_data ? pixel_data : signed_data)));
   16579             :     result = CompileRun(test_buf.start());
   16580         252 :     CHECK(result->BooleanValue(context).FromJust());
   16581             :   }
   16582             : 
   16583             :   i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
   16584             :       i::Handle<i::JSObject>::cast(jsobj)->elements()));
   16585       19602 :   for (int i = 0; i < element_count; i++) {
   16586       36720 :     array->set(i, static_cast<ElementType>(i));
   16587             :   }
   16588             : 
   16589             :   // Test complex assignments
   16590             :   result = CompileRun("function ee_op_test_complex_func(sum) {"
   16591             :                       " for (var i = 0; i < 40; ++i) {"
   16592             :                       "   sum += (ext_array[i] += 1);"
   16593             :                       "   sum += (ext_array[i] -= 1);"
   16594             :                       " } "
   16595             :                       " return sum;"
   16596             :                       "}"
   16597             :                       "sum=0;"
   16598             :                       "for (var i=0;i<10000;++i) {"
   16599             :                       "  sum=ee_op_test_complex_func(sum);"
   16600             :                       "}"
   16601             :                       "sum;");
   16602         324 :   CHECK_EQ(16000000, result->Int32Value(context).FromJust());
   16603             : 
   16604             :   // Test count operations
   16605             :   result = CompileRun("function ee_op_test_count_func(sum) {"
   16606             :                       " for (var i = 0; i < 40; ++i) {"
   16607             :                       "   sum += (++ext_array[i]);"
   16608             :                       "   sum += (--ext_array[i]);"
   16609             :                       " } "
   16610             :                       " return sum;"
   16611             :                       "}"
   16612             :                       "sum=0;"
   16613             :                       "for (var i=0;i<10000;++i) {"
   16614             :                       "  sum=ee_op_test_count_func(sum);"
   16615             :                       "}"
   16616             :                       "sum;");
   16617         324 :   CHECK_EQ(16000000, result->Int32Value(context).FromJust());
   16618             : 
   16619             :   result = CompileRun("ext_array[3] = 33;"
   16620             :                       "delete ext_array[3];"
   16621             :                       "ext_array[3];");
   16622         324 :   CHECK_EQ(33, result->Int32Value(context).FromJust());
   16623             : 
   16624             :   result = CompileRun(
   16625             :       "ext_array[0] = 10; ext_array[1] = 11;"
   16626             :       "ext_array[2] = 12; ext_array[3] = 13;"
   16627             :       "try { ext_array.__defineGetter__('2', function() { return 120; }); }"
   16628             :       "catch (e) { }"
   16629             :       "ext_array[2];");
   16630         324 :   CHECK_EQ(12, result->Int32Value(context).FromJust());
   16631             : 
   16632             :   result = CompileRun("var js_array = new Array(40);"
   16633             :                       "js_array[0] = 77;"
   16634             :                       "js_array;");
   16635         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16636             :                    ->Get(context, v8_str("0"))
   16637             :                    .ToLocalChecked()
   16638             :                    ->Int32Value(context)
   16639             :                    .FromJust());
   16640             : 
   16641             :   result = CompileRun("ext_array[1] = 23;"
   16642             :                       "ext_array.__proto__ = [];"
   16643             :                       "js_array.__proto__ = ext_array;"
   16644             :                       "js_array.concat(ext_array);");
   16645         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16646             :                    ->Get(context, v8_str("0"))
   16647             :                    .ToLocalChecked()
   16648             :                    ->Int32Value(context)
   16649             :                    .FromJust());
   16650         648 :   CHECK_EQ(23, v8::Object::Cast(*result)
   16651             :                    ->Get(context, v8_str("1"))
   16652             :                    .ToLocalChecked()
   16653             :                    ->Int32Value(context)
   16654             :                    .FromJust());
   16655             : 
   16656             :   result = CompileRun("ext_array[1] = 23;");
   16657         324 :   CHECK_EQ(23, result->Int32Value(context).FromJust());
   16658         162 : }
   16659             : 
   16660             : 
   16661             : template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
   16662             :           class ElementType>
   16663          54 : static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
   16664             :                                       ElementType low, ElementType high) {
   16665          54 :   i::FLAG_allow_natives_syntax = true;
   16666          54 :   LocalContext context;
   16667             :   i::Isolate* isolate = CcTest::i_isolate();
   16668             :   i::Factory* factory = isolate->factory();
   16669         108 :   v8::HandleScope scope(context->GetIsolate());
   16670             :   const int kElementCount = 260;
   16671             :   i::Handle<i::JSTypedArray> jsobj =
   16672          54 :       factory->NewJSTypedArray(elements_kind, kElementCount);
   16673             :   i::Handle<FixedTypedArrayClass> fixed_array(
   16674             :       FixedTypedArrayClass::cast(jsobj->elements()));
   16675          54 :   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   16676             :            fixed_array->map()->instance_type());
   16677          54 :   CHECK_EQ(kElementCount, fixed_array->length());
   16678          54 :   CcTest::CollectAllGarbage();
   16679       14094 :   for (int i = 0; i < kElementCount; i++) {
   16680       26520 :     fixed_array->set(i, static_cast<ElementType>(i));
   16681             :   }
   16682             :   // Force GC to trigger verification.
   16683          54 :   CcTest::CollectAllGarbage();
   16684       14094 :   for (int i = 0; i < kElementCount; i++) {
   16685       14040 :     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   16686             :              static_cast<int64_t>(fixed_array->get_scalar(i)));
   16687             :   }
   16688             :   v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
   16689             : 
   16690          54 :   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   16691             :       context.local(), obj, kElementCount, array_type,
   16692             :       static_cast<int64_t>(low),
   16693         108 :       static_cast<int64_t>(high));
   16694          54 : }
   16695             : 
   16696             : 
   16697       23724 : THREADED_TEST(FixedUint8Array) {
   16698             :   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   16699           6 :       i::kExternalUint8Array, 0x0, 0xFF);
   16700           6 : }
   16701             : 
   16702             : 
   16703       23724 : THREADED_TEST(FixedUint8ClampedArray) {
   16704             :   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   16705             :                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   16706           6 :       i::kExternalUint8ClampedArray, 0x0, 0xFF);
   16707           6 : }
   16708             : 
   16709             : 
   16710       23724 : THREADED_TEST(FixedInt8Array) {
   16711             :   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   16712           6 :       i::kExternalInt8Array, -0x80, 0x7F);
   16713           6 : }
   16714             : 
   16715             : 
   16716       23724 : THREADED_TEST(FixedUint16Array) {
   16717             :   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   16718           6 :       i::kExternalUint16Array, 0x0, 0xFFFF);
   16719           6 : }
   16720             : 
   16721             : 
   16722       23724 : THREADED_TEST(FixedInt16Array) {
   16723             :   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   16724           6 :       i::kExternalInt16Array, -0x8000, 0x7FFF);
   16725           6 : }
   16726             : 
   16727             : 
   16728       23724 : THREADED_TEST(FixedUint32Array) {
   16729             :   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   16730           6 :       i::kExternalUint32Array, 0x0, UINT_MAX);
   16731           6 : }
   16732             : 
   16733             : 
   16734       23724 : THREADED_TEST(FixedInt32Array) {
   16735             :   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   16736           6 :       i::kExternalInt32Array, INT_MIN, INT_MAX);
   16737           6 : }
   16738             : 
   16739             : 
   16740       23724 : THREADED_TEST(FixedFloat32Array) {
   16741             :   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   16742           6 :       i::kExternalFloat32Array, -500, 500);
   16743           6 : }
   16744             : 
   16745             : 
   16746       23724 : THREADED_TEST(FixedFloat64Array) {
   16747             :   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   16748           6 :       i::kExternalFloat64Array, -500, 500);
   16749           6 : }
   16750             : 
   16751             : 
   16752             : template <typename ElementType, typename TypedArray, class ExternalArrayClass,
   16753             :           class ArrayBufferType>
   16754         108 : void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
   16755             :                           int64_t high) {
   16756             :   const int kElementCount = 50;
   16757             : 
   16758             :   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16759             : 
   16760         216 :   LocalContext env;
   16761         108 :   v8::Isolate* isolate = env->GetIsolate();
   16762         216 :   v8::HandleScope handle_scope(isolate);
   16763             : 
   16764             :   Local<ArrayBufferType> ab =
   16765             :       ArrayBufferType::New(isolate, backing_store.start(),
   16766         108 :                            (kElementCount + 2) * sizeof(ElementType));
   16767             :   Local<TypedArray> ta =
   16768         108 :       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16769         108 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16770         108 :   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16771         108 :   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
   16772         108 :   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
   16773         432 :   CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
   16774             : 
   16775         108 :   ElementType* data = backing_store.start() + 2;
   16776        5508 :   for (int i = 0; i < kElementCount; i++) {
   16777        5400 :     data[i] = static_cast<ElementType>(i);
   16778             :   }
   16779             : 
   16780         108 :   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16781         216 :       env.local(), ta, kElementCount, array_type, low, high);
   16782         108 : }
   16783             : 
   16784             : 
   16785       23724 : THREADED_TEST(Uint8Array) {
   16786             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16787           6 :                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16788           6 : }
   16789             : 
   16790             : 
   16791       23724 : THREADED_TEST(Int8Array) {
   16792             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16793           6 :                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
   16794           6 : }
   16795             : 
   16796             : 
   16797       23724 : THREADED_TEST(Uint16Array) {
   16798             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16799           6 :                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
   16800           6 : }
   16801             : 
   16802             : 
   16803       23724 : THREADED_TEST(Int16Array) {
   16804             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16805             :                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16806           6 :                                         0x7FFF);
   16807           6 : }
   16808             : 
   16809             : 
   16810       23724 : THREADED_TEST(Uint32Array) {
   16811             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16812           6 :                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
   16813           6 : }
   16814             : 
   16815             : 
   16816       23724 : THREADED_TEST(Int32Array) {
   16817             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16818             :                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16819           6 :                                         INT_MAX);
   16820           6 : }
   16821             : 
   16822             : 
   16823       23724 : THREADED_TEST(Float32Array) {
   16824             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16825           6 :                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
   16826           6 : }
   16827             : 
   16828             : 
   16829       23724 : THREADED_TEST(Float64Array) {
   16830             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16831           6 :                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
   16832           6 : }
   16833             : 
   16834             : 
   16835       23724 : THREADED_TEST(Uint8ClampedArray) {
   16836             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16837             :                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
   16838           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16839           6 : }
   16840             : 
   16841             : 
   16842       23724 : THREADED_TEST(DataView) {
   16843             :   const int kSize = 50;
   16844             : 
   16845             :   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16846             : 
   16847          12 :   LocalContext env;
   16848           6 :   v8::Isolate* isolate = env->GetIsolate();
   16849          12 :   v8::HandleScope handle_scope(isolate);
   16850             : 
   16851             :   Local<v8::ArrayBuffer> ab =
   16852           6 :       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16853           6 :   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
   16854           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16855           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16856           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16857          24 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16858           6 : }
   16859             : 
   16860             : 
   16861       23724 : THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
   16862           6 :   LocalContext env;
   16863           6 :   v8::Isolate* isolate = env->GetIsolate();
   16864          12 :   v8::HandleScope handle_scope(isolate);
   16865             : 
   16866             :   // Make sure the pointer looks like a heap object
   16867             :   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
   16868             : 
   16869             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16870           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16871             : 
   16872             :   // Should not crash
   16873           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16874           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16875           6 :   CcTest::CollectAllGarbage();
   16876           6 :   CcTest::CollectAllGarbage();
   16877             : 
   16878             :   // Should not move the pointer
   16879          12 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16880           6 : }
   16881             : 
   16882             : 
   16883       23724 : THREADED_TEST(SkipArrayBufferDuringScavenge) {
   16884           6 :   LocalContext env;
   16885           6 :   v8::Isolate* isolate = env->GetIsolate();
   16886          12 :   v8::HandleScope handle_scope(isolate);
   16887             : 
   16888             :   // Make sure the pointer looks like a heap object
   16889           6 :   Local<v8::Object> tmp = v8::Object::New(isolate);
   16890             :   uint8_t* store_ptr =
   16891           6 :       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
   16892             : 
   16893             :   // Make `store_ptr` point to from space
   16894           6 :   CcTest::CollectGarbage(i::NEW_SPACE);
   16895             : 
   16896             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16897           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16898             : 
   16899             :   // Should not crash,
   16900             :   // i.e. backing store pointer should not be treated as a heap object pointer
   16901           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16902           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16903             : 
   16904             :   // Use `ab` to silence compiler warning
   16905          12 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16906           6 : }
   16907             : 
   16908             : 
   16909       23724 : THREADED_TEST(SharedUint8Array) {
   16910           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16911             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16912           6 :                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16913           6 : }
   16914             : 
   16915             : 
   16916       23724 : THREADED_TEST(SharedInt8Array) {
   16917           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16918             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16919             :                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
   16920           6 :                                               0x7F);
   16921           6 : }
   16922             : 
   16923             : 
   16924       23724 : THREADED_TEST(SharedUint16Array) {
   16925           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16926             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16927             :                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
   16928           6 :                                               0xFFFF);
   16929           6 : }
   16930             : 
   16931             : 
   16932       23724 : THREADED_TEST(SharedInt16Array) {
   16933           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16934             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16935             :                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16936           6 :                                               0x7FFF);
   16937           6 : }
   16938             : 
   16939             : 
   16940       23724 : THREADED_TEST(SharedUint32Array) {
   16941           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16942             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16943             :                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
   16944           6 :                                               UINT_MAX);
   16945           6 : }
   16946             : 
   16947             : 
   16948       23724 : THREADED_TEST(SharedInt32Array) {
   16949           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16950             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16951             :                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16952           6 :                                               INT_MAX);
   16953           6 : }
   16954             : 
   16955             : 
   16956       23724 : THREADED_TEST(SharedFloat32Array) {
   16957           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16958             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16959             :                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
   16960           6 :                                               500);
   16961           6 : }
   16962             : 
   16963             : 
   16964       23724 : THREADED_TEST(SharedFloat64Array) {
   16965           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16966             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16967             :                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
   16968           6 :                                               500);
   16969           6 : }
   16970             : 
   16971             : 
   16972       23724 : THREADED_TEST(SharedUint8ClampedArray) {
   16973           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16974             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16975             :                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
   16976           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16977           6 : }
   16978             : 
   16979             : 
   16980       23724 : THREADED_TEST(SharedDataView) {
   16981           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16982             :   const int kSize = 50;
   16983             : 
   16984             :   i::ScopedVector<uint8_t> backing_store(kSize + 2);
   16985             : 
   16986          12 :   LocalContext env;
   16987           6 :   v8::Isolate* isolate = env->GetIsolate();
   16988          12 :   v8::HandleScope handle_scope(isolate);
   16989             : 
   16990             :   Local<v8::SharedArrayBuffer> ab =
   16991           6 :       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16992             :   Local<v8::DataView> dv =
   16993           6 :       v8::DataView::New(ab, 2, kSize);
   16994           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16995           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16996           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16997          24 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16998           6 : }
   16999             : 
   17000             : #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                     \
   17001             :   THREADED_TEST(Is##View) {                                                 \
   17002             :     LocalContext env;                                                       \
   17003             :     v8::Isolate* isolate = env->GetIsolate();                               \
   17004             :     v8::HandleScope handle_scope(isolate);                                  \
   17005             :                                                                             \
   17006             :     Local<Value> result = CompileRun(                                       \
   17007             :         "var ab = new ArrayBuffer(128);"                                    \
   17008             :         "new " #View "(ab)");                                               \
   17009             :     CHECK(result->IsArrayBufferView());                                     \
   17010             :     CHECK(result->Is##View());                                              \
   17011             :     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
   17012             :   }
   17013             : 
   17014       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   17015       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   17016       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   17017       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   17018       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   17019       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   17020       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   17021       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   17022       23748 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   17023       23748 : IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   17024             : 
   17025             : #undef IS_ARRAY_BUFFER_VIEW_TEST
   17026             : 
   17027             : 
   17028             : 
   17029       23724 : THREADED_TEST(ScriptContextDependence) {
   17030           6 :   LocalContext c1;
   17031          12 :   v8::HandleScope scope(c1->GetIsolate());
   17032             :   const char *source = "foo";
   17033             :   v8::Local<v8::Script> dep = v8_compile(source);
   17034             :   v8::ScriptCompiler::Source script_source(
   17035             :       v8::String::NewFromUtf8(c1->GetIsolate(), source,
   17036           6 :                               v8::NewStringType::kNormal)
   17037           6 :           .ToLocalChecked());
   17038             :   v8::Local<v8::UnboundScript> indep =
   17039           6 :       v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
   17040           6 :           .ToLocalChecked();
   17041             :   c1->Global()
   17042             :       ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
   17043           6 :                                                 v8::NewStringType::kNormal)
   17044             :                             .ToLocalChecked(),
   17045          30 :             v8::Integer::New(c1->GetIsolate(), 100))
   17046          12 :       .FromJust();
   17047          18 :   CHECK_EQ(
   17048             :       dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
   17049             :       100);
   17050          24 :   CHECK_EQ(indep->BindToCurrentContext()
   17051             :                ->Run(c1.local())
   17052             :                .ToLocalChecked()
   17053             :                ->Int32Value(c1.local())
   17054             :                .FromJust(),
   17055             :            100);
   17056          12 :   LocalContext c2;
   17057             :   c2->Global()
   17058             :       ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
   17059           6 :                                                 v8::NewStringType::kNormal)
   17060             :                             .ToLocalChecked(),
   17061          30 :             v8::Integer::New(c2->GetIsolate(), 101))
   17062          12 :       .FromJust();
   17063          18 :   CHECK_EQ(
   17064             :       dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
   17065             :       100);
   17066          24 :   CHECK_EQ(indep->BindToCurrentContext()
   17067             :                ->Run(c2.local())
   17068             :                .ToLocalChecked()
   17069             :                ->Int32Value(c2.local())
   17070             :                .FromJust(),
   17071           6 :            101);
   17072           6 : }
   17073             : 
   17074             : 
   17075       23724 : THREADED_TEST(StackTrace) {
   17076           6 :   LocalContext context;
   17077          12 :   v8::HandleScope scope(context->GetIsolate());
   17078          12 :   v8::TryCatch try_catch(context->GetIsolate());
   17079             :   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   17080           6 :   v8::Local<v8::String> src = v8_str(source);
   17081           6 :   v8::Local<v8::String> origin = v8_str("stack-trace-test");
   17082             :   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   17083          30 :   CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
   17084             :                                                  &script_source)
   17085             :             .ToLocalChecked()
   17086             :             ->BindToCurrentContext()
   17087             :             ->Run(context.local())
   17088             :             .IsEmpty());
   17089           6 :   CHECK(try_catch.HasCaught());
   17090             :   v8::String::Utf8Value stack(
   17091             :       context->GetIsolate(),
   17092          18 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   17093          18 :   CHECK_NOT_NULL(strstr(*stack, "at foo (stack-trace-test"));
   17094           6 : }
   17095             : 
   17096             : 
   17097             : // Checks that a StackFrame has certain expected values.
   17098         100 : void checkStackFrame(const char* expected_script_name,
   17099             :                      const char* expected_func_name, int expected_line_number,
   17100             :                      int expected_column, bool is_eval, bool is_constructor,
   17101             :                      v8::Local<v8::StackFrame> frame) {
   17102         100 :   v8::HandleScope scope(CcTest::isolate());
   17103         300 :   v8::String::Utf8Value func_name(CcTest::isolate(), frame->GetFunctionName());
   17104         300 :   v8::String::Utf8Value script_name(CcTest::isolate(), frame->GetScriptName());
   17105         100 :   if (*script_name == nullptr) {
   17106             :     // The situation where there is no associated script, like for evals.
   17107          10 :     CHECK_NULL(expected_script_name);
   17108             :   } else {
   17109          90 :     CHECK_NOT_NULL(strstr(*script_name, expected_script_name));
   17110             :   }
   17111         200 :   CHECK_NOT_NULL(strstr(*func_name, expected_func_name));
   17112         100 :   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   17113         100 :   CHECK_EQ(expected_column, frame->GetColumn());
   17114         100 :   CHECK_EQ(is_eval, frame->IsEval());
   17115         200 :   CHECK_EQ(is_constructor, frame->IsConstructor());
   17116         100 : }
   17117             : 
   17118             : 
   17119         140 : void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   17120          35 :   v8::HandleScope scope(args.GetIsolate());
   17121             :   const char* origin = "capture-stack-trace-test";
   17122             :   const int kOverviewTest = 1;
   17123             :   const int kDetailedTest = 2;
   17124             :   const int kFunctionName = 3;
   17125             :   const int kDisplayName = 4;
   17126             :   const int kFunctionNameAndDisplayName = 5;
   17127             :   const int kDisplayNameIsNotString = 6;
   17128             :   const int kFunctionNameIsNotString = 7;
   17129             : 
   17130          35 :   CHECK_EQ(args.Length(), 1);
   17131             : 
   17132          35 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   17133          70 :   int testGroup = args[0]->Int32Value(context).FromJust();
   17134          35 :   if (testGroup == kOverviewTest) {
   17135             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17136           5 :         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   17137           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   17138             :     checkStackFrame(origin, "bar", 2, 10, false, false,
   17139           5 :                     stackTrace->GetFrame(0));
   17140           5 :     checkStackFrame(origin, "foo", 6, 3, false, true, stackTrace->GetFrame(1));
   17141             :     // This is the source string inside the eval which has the call to foo.
   17142           5 :     checkStackFrame(nullptr, "", 1, 1, true, false, stackTrace->GetFrame(2));
   17143             :     // The last frame is an anonymous function which has the initial eval call.
   17144           5 :     checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
   17145          30 :   } else if (testGroup == kDetailedTest) {
   17146             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17147           5 :         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17148           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   17149             :     checkStackFrame(origin, "bat", 4, 22, false, false,
   17150           5 :                     stackTrace->GetFrame(0));
   17151             :     checkStackFrame(origin, "baz", 8, 3, false, true,
   17152           5 :                     stackTrace->GetFrame(1));
   17153             :     bool is_eval = true;
   17154             :     // This is the source string inside the eval which has the call to baz.
   17155           5 :     checkStackFrame(nullptr, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
   17156             :     // The last frame is an anonymous function which has the initial eval call.
   17157           5 :     checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
   17158          25 :   } else if (testGroup == kFunctionName) {
   17159             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17160           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17161           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17162             :     checkStackFrame(origin, "function.name", 2, 24, false, false,
   17163           5 :                     stackTrace->GetFrame(0));
   17164          20 :   } else if (testGroup == kDisplayName) {
   17165             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17166           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17167           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17168             :     checkStackFrame(origin, "function.displayName", 2, 24, false, false,
   17169           5 :                     stackTrace->GetFrame(0));
   17170          15 :   } else if (testGroup == kFunctionNameAndDisplayName) {
   17171             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17172           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17173           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17174             :     checkStackFrame(origin, "function.displayName", 2, 24, false, false,
   17175           5 :                     stackTrace->GetFrame(0));
   17176          10 :   } else if (testGroup == kDisplayNameIsNotString) {
   17177             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17178           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17179           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17180             :     checkStackFrame(origin, "function.name", 2, 24, false, false,
   17181           5 :                     stackTrace->GetFrame(0));
   17182           5 :   } else if (testGroup == kFunctionNameIsNotString) {
   17183             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17184           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17185           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17186           5 :     checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
   17187          35 :   }
   17188          35 : }
   17189             : 
   17190             : 
   17191             : // Tests the C++ StackTrace API.
   17192             : // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   17193             : // THREADED_TEST(CaptureStackTrace) {
   17194       23723 : TEST(CaptureStackTrace) {
   17195           5 :   v8::Isolate* isolate = CcTest::isolate();
   17196           5 :   v8::HandleScope scope(isolate);
   17197           5 :   v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
   17198           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17199             :   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   17200          15 :              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   17201          10 :   LocalContext context(0, templ);
   17202             : 
   17203             :   // Test getting OVERVIEW information. Should ignore information that is not
   17204             :   // script name, function name, line number, and column offset.
   17205             :   const char *overview_source =
   17206             :     "function bar() {\n"
   17207             :     "  var y; AnalyzeStackInNativeCode(1);\n"
   17208             :     "}\n"
   17209             :     "function foo() {\n"
   17210             :     "\n"
   17211             :     "  bar();\n"
   17212             :     "}\n"
   17213             :     "var x;eval('new foo();');";
   17214           5 :   v8::Local<v8::String> overview_src = v8_str(overview_source);
   17215             :   v8::ScriptCompiler::Source script_source(overview_src,
   17216             :                                            v8::ScriptOrigin(origin));
   17217             :   v8::Local<Value> overview_result(
   17218             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
   17219           5 :           .ToLocalChecked()
   17220             :           ->BindToCurrentContext()
   17221          15 :           ->Run(context.local())
   17222           5 :           .ToLocalChecked());
   17223           5 :   CHECK(!overview_result.IsEmpty());
   17224           5 :   CHECK(overview_result->IsObject());
   17225             : 
   17226             :   // Test getting DETAILED information.
   17227             :   const char *detailed_source =
   17228             :     "function bat() {AnalyzeStackInNativeCode(2);\n"
   17229             :     "}\n"
   17230             :     "\n"
   17231             :     "function baz() {\n"
   17232             :     "  bat();\n"
   17233             :     "}\n"
   17234             :     "eval('new baz();');";
   17235           5 :   v8::Local<v8::String> detailed_src = v8_str(detailed_source);
   17236             :   // Make the script using a non-zero line and column offset.
   17237           5 :   v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   17238           5 :   v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   17239             :   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   17240             :   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   17241             :   v8::Local<v8::UnboundScript> detailed_script(
   17242             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
   17243           5 :           .ToLocalChecked());
   17244             :   v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
   17245          10 :                                        ->Run(context.local())
   17246           5 :                                        .ToLocalChecked());
   17247           5 :   CHECK(!detailed_result.IsEmpty());
   17248           5 :   CHECK(detailed_result->IsObject());
   17249             : 
   17250             :   // Test using function.name and function.displayName in stack trace
   17251             :   const char* function_name_source =
   17252             :       "function bar(function_name, display_name, testGroup) {\n"
   17253             :       "  var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
   17254             :       "  if (function_name) {\n"
   17255             :       "    Object.defineProperty(f, 'name', { value: function_name });\n"
   17256             :       "  }\n"
   17257             :       "  if (display_name) {\n"
   17258             :       "    f.displayName = display_name;"
   17259             :       "  }\n"
   17260             :       "  f()\n"
   17261             :       "}\n"
   17262             :       "bar('function.name', undefined, 3);\n"
   17263             :       "bar(undefined, 'function.displayName', 4);\n"
   17264             :       "bar('function.name', 'function.displayName', 5);\n"
   17265             :       "bar('function.name', 239, 6);\n"
   17266             :       "bar(239, undefined, 7);\n";
   17267             :   v8::Local<v8::String> function_name_src =
   17268             :       v8::String::NewFromUtf8(isolate, function_name_source,
   17269             :                               v8::NewStringType::kNormal)
   17270           5 :           .ToLocalChecked();
   17271             :   v8::ScriptCompiler::Source script_source3(function_name_src,
   17272             :                                             v8::ScriptOrigin(origin));
   17273             :   v8::Local<Value> function_name_result(
   17274             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
   17275           5 :           .ToLocalChecked()
   17276             :           ->BindToCurrentContext()
   17277          15 :           ->Run(context.local())
   17278           5 :           .ToLocalChecked());
   17279          10 :   CHECK(!function_name_result.IsEmpty());
   17280           5 : }
   17281             : 
   17282             : 
   17283           5 : static void StackTraceForUncaughtExceptionListener(
   17284             :     v8::Local<v8::Message> message, v8::Local<Value>) {
   17285           5 :   report_count++;
   17286           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17287           5 :   CHECK_EQ(2, stack_trace->GetFrameCount());
   17288             :   checkStackFrame("origin", "foo", 2, 3, false, false,
   17289           5 :                   stack_trace->GetFrame(0));
   17290             :   checkStackFrame("origin", "bar", 5, 3, false, false,
   17291           5 :                   stack_trace->GetFrame(1));
   17292           5 : }
   17293             : 
   17294             : 
   17295       23723 : TEST(CaptureStackTraceForUncaughtException) {
   17296           5 :   report_count = 0;
   17297           5 :   LocalContext env;
   17298           5 :   v8::Isolate* isolate = env->GetIsolate();
   17299          10 :   v8::HandleScope scope(isolate);
   17300           5 :   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   17301           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17302             : 
   17303             :   CompileRunWithOrigin(
   17304             :       "function foo() {\n"
   17305             :       "  throw 1;\n"
   17306             :       "};\n"
   17307             :       "function bar() {\n"
   17308             :       "  foo();\n"
   17309             :       "};",
   17310             :       "origin");
   17311           5 :   v8::Local<v8::Object> global = env->Global();
   17312             :   Local<Value> trouble =
   17313          20 :       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   17314           5 :   CHECK(trouble->IsFunction());
   17315          10 :   CHECK(Function::Cast(*trouble)
   17316             :             ->Call(env.local(), global, 0, nullptr)
   17317             :             .IsEmpty());
   17318           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17319           5 :   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   17320          10 :   CHECK_EQ(1, report_count);
   17321           5 : }
   17322             : 
   17323       23723 : TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   17324           5 :   LocalContext env;
   17325           5 :   v8::Isolate* isolate = env->GetIsolate();
   17326          10 :   v8::HandleScope scope(isolate);
   17327             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
   17328           5 :                                                      v8::StackTrace::kDetailed);
   17329             : 
   17330             :   CompileRun(
   17331             :       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   17332             :       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   17333             :       "    'isConstructor'];\n"
   17334             :       "for (var i = 0; i < setters.length; i++) {\n"
   17335             :       "  var prop = setters[i];\n"
   17336             :       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   17337             :       "}\n");
   17338             :   CompileRun("throw 'exception';");
   17339          10 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17340           5 : }
   17341             : 
   17342             : static int asm_warning_triggered = 0;
   17343             : 
   17344           4 : static void AsmJsWarningListener(v8::Local<v8::Message> message,
   17345             :                                  v8::Local<Value>) {
   17346             :   DCHECK_EQ(v8::Isolate::kMessageWarning, message->ErrorLevel());
   17347           4 :   asm_warning_triggered = 1;
   17348           4 : }
   17349             : 
   17350       23723 : TEST(AsmJsWarning) {
   17351           5 :   i::FLAG_validate_asm = true;
   17352           6 :   if (i::FLAG_suppress_asm_messages) return;
   17353             : 
   17354           4 :   LocalContext env;
   17355           4 :   v8::Isolate* isolate = env->GetIsolate();
   17356           8 :   v8::HandleScope scope(isolate);
   17357             : 
   17358           4 :   asm_warning_triggered = 0;
   17359             :   isolate->AddMessageListenerWithErrorLevel(AsmJsWarningListener,
   17360           4 :                                             v8::Isolate::kMessageAll);
   17361             :   CompileRun(
   17362             :       "function module() {\n"
   17363             :       "  'use asm';\n"
   17364             :       "  var x = 'hi';\n"
   17365             :       "  return {};\n"
   17366             :       "}\n"
   17367             :       "module();");
   17368             :   DCHECK_EQ(1, asm_warning_triggered);
   17369           8 :   isolate->RemoveMessageListeners(AsmJsWarningListener);
   17370             : }
   17371             : 
   17372             : static int error_level_message_count = 0;
   17373             : static int expected_error_level = 0;
   17374             : 
   17375          20 : static void ErrorLevelListener(v8::Local<v8::Message> message,
   17376             :                                v8::Local<Value>) {
   17377             :   DCHECK_EQ(expected_error_level, message->ErrorLevel());
   17378          20 :   ++error_level_message_count;
   17379          20 : }
   17380             : 
   17381       23723 : TEST(ErrorLevelWarning) {
   17382           5 :   LocalContext env;
   17383           5 :   v8::Isolate* isolate = env->GetIsolate();
   17384             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   17385          10 :   v8::HandleScope scope(isolate);
   17386             : 
   17387             :   const char* source = "fake = 1;";
   17388           5 :   v8::Local<v8::Script> lscript = CompileWithOrigin(source, "test");
   17389             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   17390          10 :       v8::Utils::OpenHandle(*lscript->GetUnboundScript()));
   17391           5 :   CHECK(obj->script()->IsScript());
   17392             :   i::Handle<i::Script> script(i::Script::cast(obj->script()));
   17393             : 
   17394             :   int levels[] = {
   17395             :       v8::Isolate::kMessageLog, v8::Isolate::kMessageInfo,
   17396             :       v8::Isolate::kMessageDebug, v8::Isolate::kMessageWarning,
   17397           5 :   };
   17398           5 :   error_level_message_count = 0;
   17399             :   isolate->AddMessageListenerWithErrorLevel(ErrorLevelListener,
   17400           5 :                                             v8::Isolate::kMessageAll);
   17401          25 :   for (size_t i = 0; i < arraysize(levels); i++) {
   17402          20 :     i::MessageLocation location(script, 0, 0);
   17403             :     i::Handle<i::String> msg(i_isolate->factory()->InternalizeOneByteString(
   17404          20 :         STATIC_CHAR_VECTOR("test")));
   17405             :     i::Handle<i::JSMessageObject> message =
   17406             :         i::MessageHandler::MakeMessageObject(
   17407             :             i_isolate, i::MessageTemplate::kAsmJsInvalid, &location, msg,
   17408          20 :             i::Handle<i::FixedArray>::null());
   17409          20 :     message->set_error_level(levels[i]);
   17410          20 :     expected_error_level = levels[i];
   17411          20 :     i::MessageHandler::ReportMessage(i_isolate, &location, message);
   17412             :   }
   17413           5 :   isolate->RemoveMessageListeners(ErrorLevelListener);
   17414           5 :   DCHECK_EQ(arraysize(levels), error_level_message_count);
   17415           5 : }
   17416             : 
   17417           5 : static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
   17418             :                                            v8::Local<Value>) {
   17419           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17420           5 :   CHECK_EQ(5, stack_trace->GetFrameCount());
   17421             :   checkStackFrame("origin", "foo:0", 4, 7, false, false,
   17422           5 :                   stack_trace->GetFrame(0));
   17423             :   checkStackFrame("origin", "foo:1", 5, 27, false, false,
   17424           5 :                   stack_trace->GetFrame(1));
   17425             :   checkStackFrame("origin", "foo", 5, 27, false, false,
   17426           5 :                   stack_trace->GetFrame(2));
   17427             :   checkStackFrame("origin", "foo", 5, 27, false, false,
   17428           5 :                   stack_trace->GetFrame(3));
   17429           5 :   checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
   17430           5 : }
   17431             : 
   17432             : 
   17433       23723 : TEST(GetStackTraceContainsFunctionsWithFunctionName) {
   17434           5 :   LocalContext env;
   17435           5 :   v8::Isolate* isolate = env->GetIsolate();
   17436          10 :   v8::HandleScope scope(isolate);
   17437             : 
   17438             :   CompileRunWithOrigin(
   17439             :       "function gen(name, counter) {\n"
   17440             :       "  var f = function foo() {\n"
   17441             :       "    if (counter === 0)\n"
   17442             :       "      throw 1;\n"
   17443             :       "    gen(name, counter - 1)();\n"
   17444             :       "  };\n"
   17445             :       "  if (counter == 3) {\n"
   17446             :       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
   17447             :       "  } else {\n"
   17448             :       "    Object.defineProperty(f, 'name', {writable:true});\n"
   17449             :       "    if (counter == 2)\n"
   17450             :       "      f.name = 42;\n"
   17451             :       "    else\n"
   17452             :       "      f.name = name + ':' + counter;\n"
   17453             :       "  }\n"
   17454             :       "  return f;\n"
   17455             :       "};",
   17456             :       "origin");
   17457             : 
   17458           5 :   isolate->AddMessageListener(StackTraceFunctionNameListener);
   17459           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17460             :   CompileRunWithOrigin("gen('foo', 3)();", "origin");
   17461           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17462          10 :   isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
   17463           5 : }
   17464             : 
   17465             : 
   17466           5 : static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
   17467             :                                      v8::Local<v8::Value> data) {
   17468             :   // Use the frame where JavaScript is called from.
   17469           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17470           5 :   CHECK(!stack_trace.IsEmpty());
   17471           5 :   int frame_count = stack_trace->GetFrameCount();
   17472           5 :   CHECK_EQ(3, frame_count);
   17473           5 :   int line_number[] = {1, 2, 5};
   17474          20 :   for (int i = 0; i < frame_count; i++) {
   17475          30 :     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   17476             :   }
   17477           5 : }
   17478             : 
   17479             : 
   17480             : // Test that we only return the stack trace at the site where the exception
   17481             : // is first thrown (not where it is rethrown).
   17482       23723 : TEST(RethrowStackTrace) {
   17483           5 :   LocalContext env;
   17484           5 :   v8::Isolate* isolate = env->GetIsolate();
   17485          10 :   v8::HandleScope scope(isolate);
   17486             :   // We make sure that
   17487             :   // - the stack trace of the ReferenceError in g() is reported.
   17488             :   // - the stack trace is not overwritten when e1 is rethrown by t().
   17489             :   // - the stack trace of e2 does not overwrite that of e1.
   17490             :   const char* source =
   17491             :       "function g() { error; }          \n"
   17492             :       "function f() { g(); }            \n"
   17493             :       "function t(e) { throw e; }       \n"
   17494             :       "try {                            \n"
   17495             :       "  f();                           \n"
   17496             :       "} catch (e1) {                   \n"
   17497             :       "  try {                          \n"
   17498             :       "    error;                       \n"
   17499             :       "  } catch (e2) {                 \n"
   17500             :       "    t(e1);                       \n"
   17501             :       "  }                              \n"
   17502             :       "}                                \n";
   17503           5 :   isolate->AddMessageListener(RethrowStackTraceHandler);
   17504           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17505             :   CompileRun(source);
   17506           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17507          10 :   isolate->RemoveMessageListeners(RethrowStackTraceHandler);
   17508           5 : }
   17509             : 
   17510             : 
   17511           5 : static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
   17512             :                                               v8::Local<v8::Value> data) {
   17513           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17514           5 :   CHECK(!stack_trace.IsEmpty());
   17515           5 :   int frame_count = stack_trace->GetFrameCount();
   17516           5 :   CHECK_EQ(2, frame_count);
   17517           5 :   int line_number[] = {3, 7};
   17518          15 :   for (int i = 0; i < frame_count; i++) {
   17519          20 :     CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
   17520             :   }
   17521           5 : }
   17522             : 
   17523             : 
   17524             : // Test that we do not recognize identity for primitive exceptions.
   17525       23723 : TEST(RethrowPrimitiveStackTrace) {
   17526           5 :   LocalContext env;
   17527           5 :   v8::Isolate* isolate = env->GetIsolate();
   17528          10 :   v8::HandleScope scope(isolate);
   17529             :   // We do not capture stack trace for non Error objects on creation time.
   17530             :   // Instead, we capture the stack trace on last throw.
   17531             :   const char* source =
   17532             :       "function g() { throw 404; }      \n"
   17533             :       "function f() { g(); }            \n"
   17534             :       "function t(e) { throw e; }       \n"
   17535             :       "try {                            \n"
   17536             :       "  f();                           \n"
   17537             :       "} catch (e1) {                   \n"
   17538             :       "  t(e1)                          \n"
   17539             :       "}                                \n";
   17540           5 :   isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
   17541           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17542             :   CompileRun(source);
   17543           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17544          10 :   isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   17545           5 : }
   17546             : 
   17547             : 
   17548           5 : static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
   17549             :                                              v8::Local<v8::Value> data) {
   17550             :   // Use the frame where JavaScript is called from.
   17551           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17552           5 :   CHECK(!stack_trace.IsEmpty());
   17553           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   17554          10 :   CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
   17555           5 : }
   17556             : 
   17557             : 
   17558             : // Test that the stack trace is captured when the error object is created and
   17559             : // not where it is thrown.
   17560       23723 : TEST(RethrowExistingStackTrace) {
   17561           5 :   LocalContext env;
   17562           5 :   v8::Isolate* isolate = env->GetIsolate();
   17563          10 :   v8::HandleScope scope(isolate);
   17564             :   const char* source =
   17565             :       "var e = new Error();           \n"
   17566             :       "throw e;                       \n";
   17567           5 :   isolate->AddMessageListener(RethrowExistingStackTraceHandler);
   17568           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17569             :   CompileRun(source);
   17570           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17571          10 :   isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
   17572           5 : }
   17573             : 
   17574             : 
   17575           5 : static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
   17576             :                                                v8::Local<v8::Value> data) {
   17577             :   // Use the frame where JavaScript is called from.
   17578           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17579           5 :   CHECK(!stack_trace.IsEmpty());
   17580           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   17581          10 :   CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
   17582           5 : }
   17583             : 
   17584             : 
   17585             : // Test that the stack trace is captured where the bogus Error object is thrown.
   17586       23723 : TEST(RethrowBogusErrorStackTrace) {
   17587           5 :   LocalContext env;
   17588           5 :   v8::Isolate* isolate = env->GetIsolate();
   17589          10 :   v8::HandleScope scope(isolate);
   17590             :   const char* source =
   17591             :       "var e = {__proto__: new Error()} \n"
   17592             :       "throw e;                         \n";
   17593           5 :   isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
   17594           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17595             :   CompileRun(source);
   17596           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17597          10 :   isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   17598           5 : }
   17599             : 
   17600             : 
   17601             : v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
   17602             : int promise_reject_counter = 0;
   17603             : int promise_revoke_counter = 0;
   17604             : int promise_reject_msg_line_number = -1;
   17605             : int promise_reject_msg_column_number = -1;
   17606             : int promise_reject_line_number = -1;
   17607             : int promise_reject_column_number = -1;
   17608             : int promise_reject_frame_count = -1;
   17609             : 
   17610         110 : void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
   17611         110 :   v8::Local<v8::Object> global = CcTest::global();
   17612         110 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17613         110 :   CHECK_EQ(v8::Promise::PromiseState::kRejected,
   17614             :            reject_message.GetPromise()->State());
   17615         110 :   if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
   17616          80 :     promise_reject_counter++;
   17617         160 :     global->Set(context, v8_str("rejected"), reject_message.GetPromise())
   17618         160 :         .FromJust();
   17619         240 :     global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
   17620             :     v8::Local<v8::Message> message = v8::Exception::CreateMessage(
   17621          80 :         CcTest::isolate(), reject_message.GetValue());
   17622          80 :     v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17623             : 
   17624         160 :     promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
   17625             :     promise_reject_msg_column_number =
   17626         160 :         message->GetStartColumn(context).FromJust() + 1;
   17627             : 
   17628          80 :     if (!stack_trace.IsEmpty()) {
   17629          35 :       promise_reject_frame_count = stack_trace->GetFrameCount();
   17630          35 :       if (promise_reject_frame_count > 0) {
   17631         150 :         CHECK(stack_trace->GetFrame(0)
   17632             :                   ->GetScriptName()
   17633             :                   ->Equals(context, v8_str("pro"))
   17634             :                   .FromJust());
   17635          60 :         promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
   17636          60 :         promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
   17637             :       } else {
   17638           5 :         promise_reject_line_number = -1;
   17639           5 :         promise_reject_column_number = -1;
   17640             :       }
   17641             :     }
   17642             :   } else {
   17643          30 :     promise_revoke_counter++;
   17644          60 :     global->Set(context, v8_str("revoked"), reject_message.GetPromise())
   17645          60 :         .FromJust();
   17646          30 :     CHECK(reject_message.GetValue().IsEmpty());
   17647             :   }
   17648         110 : }
   17649             : 
   17650             : 
   17651         550 : v8::Local<v8::Promise> GetPromise(const char* name) {
   17652             :   return v8::Local<v8::Promise>::Cast(
   17653             :       CcTest::global()
   17654        1650 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   17655        1100 :           .ToLocalChecked());
   17656             : }
   17657             : 
   17658             : 
   17659          35 : v8::Local<v8::Value> RejectValue() {
   17660             :   return CcTest::global()
   17661         105 :       ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17662          70 :       .ToLocalChecked();
   17663             : }
   17664             : 
   17665             : 
   17666          40 : void ResetPromiseStates() {
   17667          40 :   promise_reject_counter = 0;
   17668          40 :   promise_revoke_counter = 0;
   17669          40 :   promise_reject_msg_line_number = -1;
   17670          40 :   promise_reject_msg_column_number = -1;
   17671          40 :   promise_reject_line_number = -1;
   17672          40 :   promise_reject_column_number = -1;
   17673          40 :   promise_reject_frame_count = -1;
   17674             : 
   17675          40 :   v8::Local<v8::Object> global = CcTest::global();
   17676          40 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17677         160 :   global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
   17678         160 :   global->Set(context, v8_str("value"), v8_str("")).FromJust();
   17679         160 :   global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
   17680          40 : }
   17681             : 
   17682             : 
   17683       23723 : TEST(PromiseRejectCallback) {
   17684           5 :   LocalContext env;
   17685           5 :   v8::Isolate* isolate = env->GetIsolate();
   17686          10 :   v8::HandleScope scope(isolate);
   17687             : 
   17688           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17689             : 
   17690           5 :   ResetPromiseStates();
   17691             : 
   17692             :   // Create promise p0.
   17693             :   CompileRun(
   17694             :       "var reject;            \n"
   17695             :       "var p0 = new Promise(  \n"
   17696             :       "  function(res, rej) { \n"
   17697             :       "    reject = rej;      \n"
   17698             :       "  }                    \n"
   17699             :       ");                     \n");
   17700          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17701           5 :   CHECK_EQ(0, promise_reject_counter);
   17702           5 :   CHECK_EQ(0, promise_revoke_counter);
   17703             : 
   17704             :   // Add resolve handler (and default reject handler) to p0.
   17705             :   CompileRun("var p1 = p0.then(function(){});");
   17706          10 :   CHECK(GetPromise("p0")->HasHandler());
   17707          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17708           5 :   CHECK_EQ(0, promise_reject_counter);
   17709           5 :   CHECK_EQ(0, promise_revoke_counter);
   17710             : 
   17711             :   // Reject p0.
   17712             :   CompileRun("reject('ppp');");
   17713          10 :   CHECK(GetPromise("p0")->HasHandler());
   17714          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17715           5 :   CHECK_EQ(1, promise_reject_counter);
   17716           5 :   CHECK_EQ(0, promise_revoke_counter);
   17717           5 :   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
   17718          20 :   CHECK(
   17719             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
   17720          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17721             : 
   17722             :   // Reject p0 again. Callback is not triggered again.
   17723             :   CompileRun("reject();");
   17724          10 :   CHECK(GetPromise("p0")->HasHandler());
   17725          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17726           5 :   CHECK_EQ(1, promise_reject_counter);
   17727           5 :   CHECK_EQ(0, promise_revoke_counter);
   17728             : 
   17729             :   // Add resolve handler to p1.
   17730             :   CompileRun("var p2 = p1.then(function(){});");
   17731          10 :   CHECK(GetPromise("p0")->HasHandler());
   17732          10 :   CHECK(GetPromise("p1")->HasHandler());
   17733          10 :   CHECK(!GetPromise("p2")->HasHandler());
   17734           5 :   CHECK_EQ(2, promise_reject_counter);
   17735           5 :   CHECK_EQ(1, promise_revoke_counter);
   17736          20 :   CHECK(
   17737             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
   17738          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17739          20 :   CHECK(
   17740             :       GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
   17741             : 
   17742           5 :   ResetPromiseStates();
   17743             : 
   17744             :   // Create promise q0.
   17745             :   CompileRun(
   17746             :       "var q0 = new Promise(  \n"
   17747             :       "  function(res, rej) { \n"
   17748             :       "    reject = rej;      \n"
   17749             :       "  }                    \n"
   17750             :       ");                     \n");
   17751          10 :   CHECK(!GetPromise("q0")->HasHandler());
   17752           5 :   CHECK_EQ(0, promise_reject_counter);
   17753           5 :   CHECK_EQ(0, promise_revoke_counter);
   17754             : 
   17755             :   // Add reject handler to q0.
   17756             :   CompileRun("var q1 = q0.catch(function() {});");
   17757          10 :   CHECK(GetPromise("q0")->HasHandler());
   17758          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17759           5 :   CHECK_EQ(0, promise_reject_counter);
   17760           5 :   CHECK_EQ(0, promise_revoke_counter);
   17761             : 
   17762             :   // Reject q0.
   17763             :   CompileRun("reject('qq')");
   17764          10 :   CHECK(GetPromise("q0")->HasHandler());
   17765          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17766           5 :   CHECK_EQ(0, promise_reject_counter);
   17767           5 :   CHECK_EQ(0, promise_revoke_counter);
   17768             : 
   17769             :   // Add a new reject handler, which rejects by returning Promise.reject().
   17770             :   // The returned promise q_ triggers a reject callback at first, only to
   17771             :   // revoke it when returning it causes q2 to be rejected.
   17772             :   CompileRun(
   17773             :       "var q_;"
   17774             :       "var q2 = q0.catch(               \n"
   17775             :       "   function() {                  \n"
   17776             :       "     q_ = Promise.reject('qqq'); \n"
   17777             :       "     return q_;                  \n"
   17778             :       "   }                             \n"
   17779             :       ");                               \n");
   17780          10 :   CHECK(GetPromise("q0")->HasHandler());
   17781          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17782          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17783          10 :   CHECK(GetPromise("q_")->HasHandler());
   17784           5 :   CHECK_EQ(2, promise_reject_counter);
   17785           5 :   CHECK_EQ(1, promise_revoke_counter);
   17786          20 :   CHECK(
   17787             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
   17788          20 :   CHECK(
   17789             :       GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
   17790          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
   17791             : 
   17792             :   // Add a reject handler to the resolved q1, which rejects by throwing.
   17793             :   CompileRun(
   17794             :       "var q3 = q1.then(  \n"
   17795             :       "   function() {    \n"
   17796             :       "     throw 'qqqq'; \n"
   17797             :       "   }               \n"
   17798             :       ");                 \n");
   17799          10 :   CHECK(GetPromise("q0")->HasHandler());
   17800          10 :   CHECK(GetPromise("q1")->HasHandler());
   17801          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17802          10 :   CHECK(!GetPromise("q3")->HasHandler());
   17803           5 :   CHECK_EQ(3, promise_reject_counter);
   17804           5 :   CHECK_EQ(1, promise_revoke_counter);
   17805          20 :   CHECK(
   17806             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
   17807          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
   17808             : 
   17809           5 :   ResetPromiseStates();
   17810             : 
   17811             :   // Create promise r0, which has three handlers, two of which handle rejects.
   17812             :   CompileRun(
   17813             :       "var r0 = new Promise(             \n"
   17814             :       "  function(res, rej) {            \n"
   17815             :       "    reject = rej;                 \n"
   17816             :       "  }                               \n"
   17817             :       ");                                \n"
   17818             :       "var r1 = r0.catch(function() {}); \n"
   17819             :       "var r2 = r0.then(function() {});  \n"
   17820             :       "var r3 = r0.then(function() {},   \n"
   17821             :       "                 function() {});  \n");
   17822          10 :   CHECK(GetPromise("r0")->HasHandler());
   17823          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17824          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17825          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17826           5 :   CHECK_EQ(0, promise_reject_counter);
   17827           5 :   CHECK_EQ(0, promise_revoke_counter);
   17828             : 
   17829             :   // Reject r0.
   17830             :   CompileRun("reject('rrr')");
   17831          10 :   CHECK(GetPromise("r0")->HasHandler());
   17832          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17833          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17834          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17835           5 :   CHECK_EQ(1, promise_reject_counter);
   17836           5 :   CHECK_EQ(0, promise_revoke_counter);
   17837          20 :   CHECK(
   17838             :       GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
   17839          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17840             : 
   17841             :   // Add reject handler to r2.
   17842             :   CompileRun("var r4 = r2.catch(function() {});");
   17843          10 :   CHECK(GetPromise("r0")->HasHandler());
   17844          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17845          10 :   CHECK(GetPromise("r2")->HasHandler());
   17846          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17847          10 :   CHECK(!GetPromise("r4")->HasHandler());
   17848           5 :   CHECK_EQ(1, promise_reject_counter);
   17849           5 :   CHECK_EQ(1, promise_revoke_counter);
   17850          20 :   CHECK(
   17851             :       GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
   17852          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17853             : 
   17854             :   // Add reject handlers to r4.
   17855             :   CompileRun("var r5 = r4.then(function() {}, function() {});");
   17856          10 :   CHECK(GetPromise("r0")->HasHandler());
   17857          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17858          10 :   CHECK(GetPromise("r2")->HasHandler());
   17859          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17860          10 :   CHECK(GetPromise("r4")->HasHandler());
   17861          10 :   CHECK(!GetPromise("r5")->HasHandler());
   17862           5 :   CHECK_EQ(1, promise_reject_counter);
   17863           5 :   CHECK_EQ(1, promise_revoke_counter);
   17864             : 
   17865           5 :   ResetPromiseStates();
   17866             : 
   17867             :   // Create promise s0, which has three handlers, none of which handle rejects.
   17868             :   CompileRun(
   17869             :       "var s0 = new Promise(            \n"
   17870             :       "  function(res, rej) {           \n"
   17871             :       "    reject = rej;                \n"
   17872             :       "  }                              \n"
   17873             :       ");                               \n"
   17874             :       "var s1 = s0.then(function() {}); \n"
   17875             :       "var s2 = s0.then(function() {}); \n"
   17876             :       "var s3 = s0.then(function() {}); \n");
   17877          10 :   CHECK(GetPromise("s0")->HasHandler());
   17878          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17879          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17880          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17881           5 :   CHECK_EQ(0, promise_reject_counter);
   17882           5 :   CHECK_EQ(0, promise_revoke_counter);
   17883             : 
   17884             :   // Reject s0.
   17885             :   CompileRun("reject('sss')");
   17886          10 :   CHECK(GetPromise("s0")->HasHandler());
   17887          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17888          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17889          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17890           5 :   CHECK_EQ(3, promise_reject_counter);
   17891           5 :   CHECK_EQ(0, promise_revoke_counter);
   17892          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
   17893             : 
   17894             :   // Test stack frames.
   17895           5 :   env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   17896             : 
   17897           5 :   ResetPromiseStates();
   17898             : 
   17899             :   // Create promise t0, which is rejected in the constructor with an error.
   17900             :   CompileRunWithOrigin(
   17901             :       "var t0 = new Promise(  \n"
   17902             :       "  function(res, rej) { \n"
   17903             :       "    reference_error;   \n"
   17904             :       "  }                    \n"
   17905             :       ");                     \n",
   17906           5 :       "pro", 0, 0);
   17907          10 :   CHECK(!GetPromise("t0")->HasHandler());
   17908           5 :   CHECK_EQ(1, promise_reject_counter);
   17909           5 :   CHECK_EQ(0, promise_revoke_counter);
   17910           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17911           5 :   CHECK_EQ(3, promise_reject_line_number);
   17912           5 :   CHECK_EQ(5, promise_reject_column_number);
   17913           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   17914           5 :   CHECK_EQ(5, promise_reject_msg_column_number);
   17915             : 
   17916           5 :   ResetPromiseStates();
   17917             : 
   17918             :   // Create promise u0 and chain u1 to it, which is rejected via throw.
   17919             :   CompileRunWithOrigin(
   17920             :       "var u0 = Promise.resolve();        \n"
   17921             :       "var u1 = u0.then(                  \n"
   17922             :       "           function() {            \n"
   17923             :       "             (function() {         \n"
   17924             :       "                throw new Error(); \n"
   17925             :       "              })();                \n"
   17926             :       "           }                       \n"
   17927             :       "         );                        \n",
   17928           5 :       "pro", 0, 0);
   17929          10 :   CHECK(GetPromise("u0")->HasHandler());
   17930          10 :   CHECK(!GetPromise("u1")->HasHandler());
   17931           5 :   CHECK_EQ(1, promise_reject_counter);
   17932           5 :   CHECK_EQ(0, promise_revoke_counter);
   17933           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17934           5 :   CHECK_EQ(5, promise_reject_line_number);
   17935           5 :   CHECK_EQ(23, promise_reject_column_number);
   17936           5 :   CHECK_EQ(5, promise_reject_msg_line_number);
   17937           5 :   CHECK_EQ(23, promise_reject_msg_column_number);
   17938             : 
   17939             :   // Throw in u3, which handles u1's rejection.
   17940             :   CompileRunWithOrigin(
   17941             :       "function f() {                \n"
   17942             :       "  return (function() {        \n"
   17943             :       "    return new Error();       \n"
   17944             :       "  })();                       \n"
   17945             :       "}                             \n"
   17946             :       "var u2 = Promise.reject(f()); \n"
   17947             :       "var u3 = u1.catch(            \n"
   17948             :       "           function() {       \n"
   17949             :       "             return u2;       \n"
   17950             :       "           }                  \n"
   17951             :       "         );                   \n",
   17952           5 :       "pro", 0, 0);
   17953          10 :   CHECK(GetPromise("u0")->HasHandler());
   17954          10 :   CHECK(GetPromise("u1")->HasHandler());
   17955          10 :   CHECK(GetPromise("u2")->HasHandler());
   17956          10 :   CHECK(!GetPromise("u3")->HasHandler());
   17957           5 :   CHECK_EQ(3, promise_reject_counter);
   17958           5 :   CHECK_EQ(2, promise_revoke_counter);
   17959           5 :   CHECK_EQ(3, promise_reject_frame_count);
   17960           5 :   CHECK_EQ(3, promise_reject_line_number);
   17961           5 :   CHECK_EQ(12, promise_reject_column_number);
   17962           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   17963           5 :   CHECK_EQ(12, promise_reject_msg_column_number);
   17964             : 
   17965           5 :   ResetPromiseStates();
   17966             : 
   17967             :   // Create promise rejected promise v0, which is incorrectly handled by v1
   17968             :   // via chaining cycle.
   17969             :   CompileRunWithOrigin(
   17970             :       "var v0 = Promise.reject(); \n"
   17971             :       "var v1 = v0.catch(         \n"
   17972             :       "           function() {    \n"
   17973             :       "             return v1;    \n"
   17974             :       "           }               \n"
   17975             :       "         );                \n",
   17976           5 :       "pro", 0, 0);
   17977          10 :   CHECK(GetPromise("v0")->HasHandler());
   17978          10 :   CHECK(!GetPromise("v1")->HasHandler());
   17979           5 :   CHECK_EQ(2, promise_reject_counter);
   17980           5 :   CHECK_EQ(1, promise_revoke_counter);
   17981           5 :   CHECK_EQ(0, promise_reject_frame_count);
   17982           5 :   CHECK_EQ(-1, promise_reject_line_number);
   17983           5 :   CHECK_EQ(-1, promise_reject_column_number);
   17984             : 
   17985           5 :   ResetPromiseStates();
   17986             : 
   17987             :   // Create promise t1, which rejects by throwing syntax error from eval.
   17988             :   CompileRunWithOrigin(
   17989             :       "var t1 = new Promise(   \n"
   17990             :       "  function(res, rej) {  \n"
   17991             :       "    var content = '\\n\\\n"
   17992             :       "      }';               \n"
   17993             :       "    eval(content);      \n"
   17994             :       "  }                     \n"
   17995             :       ");                      \n",
   17996           5 :       "pro", 0, 0);
   17997          10 :   CHECK(!GetPromise("t1")->HasHandler());
   17998           5 :   CHECK_EQ(1, promise_reject_counter);
   17999           5 :   CHECK_EQ(0, promise_revoke_counter);
   18000           5 :   CHECK_EQ(2, promise_reject_frame_count);
   18001           5 :   CHECK_EQ(5, promise_reject_line_number);
   18002           5 :   CHECK_EQ(10, promise_reject_column_number);
   18003           5 :   CHECK_EQ(2, promise_reject_msg_line_number);
   18004          10 :   CHECK_EQ(7, promise_reject_msg_column_number);
   18005           5 : }
   18006             : 
   18007             : 
   18008          10 : void AnalyzeStackOfEvalWithSourceURL(
   18009          50 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18010          10 :   v8::HandleScope scope(args.GetIsolate());
   18011             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18012          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18013          10 :   CHECK_EQ(5, stackTrace->GetFrameCount());
   18014          10 :   v8::Local<v8::String> url = v8_str("eval_url");
   18015          40 :   for (int i = 0; i < 3; i++) {
   18016             :     v8::Local<v8::String> name =
   18017          60 :         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   18018          30 :     CHECK(!name.IsEmpty());
   18019          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18020          10 :   }
   18021          10 : }
   18022             : 
   18023             : 
   18024       23723 : TEST(SourceURLInStackTrace) {
   18025           5 :   v8::Isolate* isolate = CcTest::isolate();
   18026           5 :   v8::HandleScope scope(isolate);
   18027           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18028             :   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   18029             :              v8::FunctionTemplate::New(isolate,
   18030          15 :                                        AnalyzeStackOfEvalWithSourceURL));
   18031          10 :   LocalContext context(0, templ);
   18032             : 
   18033             :   const char *source =
   18034             :     "function outer() {\n"
   18035             :     "function bar() {\n"
   18036             :     "  AnalyzeStackOfEvalWithSourceURL();\n"
   18037             :     "}\n"
   18038             :     "function foo() {\n"
   18039             :     "\n"
   18040             :     "  bar();\n"
   18041             :     "}\n"
   18042             :     "foo();\n"
   18043             :     "}\n"
   18044             :     "eval('(' + outer +')()%s');";
   18045             : 
   18046             :   i::ScopedVector<char> code(1024);
   18047           5 :   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   18048           5 :   CHECK(CompileRun(code.start())->IsUndefined());
   18049           5 :   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   18050          10 :   CHECK(CompileRun(code.start())->IsUndefined());
   18051           5 : }
   18052             : 
   18053             : 
   18054             : static int scriptIdInStack[2];
   18055             : 
   18056           5 : void AnalyzeScriptIdInStack(
   18057          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18058           5 :   v8::HandleScope scope(args.GetIsolate());
   18059             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18060           5 :       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   18061           5 :   CHECK_EQ(2, stackTrace->GetFrameCount());
   18062          10 :   for (int i = 0; i < 2; i++) {
   18063          20 :     scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
   18064           5 :   }
   18065           5 : }
   18066             : 
   18067             : 
   18068       23723 : TEST(ScriptIdInStackTrace) {
   18069           5 :   v8::Isolate* isolate = CcTest::isolate();
   18070           5 :   v8::HandleScope scope(isolate);
   18071           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18072             :   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   18073          15 :              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   18074          10 :   LocalContext context(0, templ);
   18075             : 
   18076             :   v8::Local<v8::String> scriptSource = v8_str(
   18077             :       "function foo() {\n"
   18078             :       "  AnalyzeScriptIdInStack();"
   18079             :       "}\n"
   18080           5 :       "foo();\n");
   18081             :   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
   18082           5 :   script->Run(context.local()).ToLocalChecked();
   18083          15 :   for (int i = 0; i < 2; i++) {
   18084          10 :     CHECK_NE(scriptIdInStack[i], v8::Message::kNoScriptIdInfo);
   18085          20 :     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   18086           5 :   }
   18087           5 : }
   18088             : 
   18089             : 
   18090          10 : void AnalyzeStackOfInlineScriptWithSourceURL(
   18091          50 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18092          10 :   v8::HandleScope scope(args.GetIsolate());
   18093             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18094          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18095          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   18096          10 :   v8::Local<v8::String> url = v8_str("source_url");
   18097          40 :   for (int i = 0; i < 3; i++) {
   18098             :     v8::Local<v8::String> name =
   18099          60 :         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   18100          30 :     CHECK(!name.IsEmpty());
   18101          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18102          10 :   }
   18103          10 : }
   18104             : 
   18105             : 
   18106       23723 : TEST(InlineScriptWithSourceURLInStackTrace) {
   18107           5 :   v8::Isolate* isolate = CcTest::isolate();
   18108           5 :   v8::HandleScope scope(isolate);
   18109           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18110             :   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   18111             :              v8::FunctionTemplate::New(
   18112          15 :                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   18113          10 :   LocalContext context(0, templ);
   18114             : 
   18115             :   const char *source =
   18116             :     "function outer() {\n"
   18117             :     "function bar() {\n"
   18118             :     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   18119             :     "}\n"
   18120             :     "function foo() {\n"
   18121             :     "\n"
   18122             :     "  bar();\n"
   18123             :     "}\n"
   18124             :     "foo();\n"
   18125             :     "}\n"
   18126             :     "outer()\n%s";
   18127             : 
   18128             :   i::ScopedVector<char> code(1024);
   18129           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18130          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   18131           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   18132          15 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   18133           5 : }
   18134             : 
   18135         325 : void SetPromise(const char* name, v8::Local<v8::Promise> promise) {
   18136             :   CcTest::global()
   18137         975 :       ->Set(CcTest::isolate()->GetCurrentContext(), v8_str(name), promise)
   18138         650 :       .FromJust();
   18139         325 : }
   18140             : 
   18141           5 : class PromiseHookData {
   18142             :  public:
   18143             :   int before_hook_count = 0;
   18144             :   int after_hook_count = 0;
   18145             :   int promise_hook_count = 0;
   18146             :   int parent_promise_count = 0;
   18147             :   bool check_value = true;
   18148             :   std::string promise_hook_value;
   18149             : 
   18150             :   void Reset() {
   18151          40 :     before_hook_count = 0;
   18152          40 :     after_hook_count = 0;
   18153          40 :     promise_hook_count = 0;
   18154          40 :     parent_promise_count = 0;
   18155          40 :     check_value = true;
   18156          40 :     promise_hook_value = "";
   18157             :   }
   18158             : };
   18159             : 
   18160             : PromiseHookData* promise_hook_data;
   18161             : 
   18162         285 : void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise,
   18163             :                        v8::Local<v8::Value> parentPromise) {
   18164         285 :   promise_hook_data->promise_hook_count++;
   18165         285 :   switch (type) {
   18166             :     case v8::PromiseHookType::kInit:
   18167         100 :       SetPromise("init", promise);
   18168             : 
   18169         100 :       if (!parentPromise->IsUndefined()) {
   18170          40 :         promise_hook_data->parent_promise_count++;
   18171          40 :         SetPromise("parent", v8::Local<v8::Promise>::Cast(parentPromise));
   18172             :       }
   18173             : 
   18174             :       break;
   18175             :     case v8::PromiseHookType::kResolve:
   18176          95 :       SetPromise("resolve", promise);
   18177          95 :       break;
   18178             :     case v8::PromiseHookType::kBefore:
   18179          45 :       promise_hook_data->before_hook_count++;
   18180          45 :       CHECK(promise_hook_data->before_hook_count >
   18181             :             promise_hook_data->after_hook_count);
   18182         270 :       CHECK(CcTest::global()
   18183             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18184             :                 .ToLocalChecked()
   18185             :                 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str(""))
   18186             :                 .FromJust());
   18187          45 :       SetPromise("before", promise);
   18188          45 :       break;
   18189             :     case v8::PromiseHookType::kAfter:
   18190          45 :       promise_hook_data->after_hook_count++;
   18191          45 :       CHECK(promise_hook_data->after_hook_count <=
   18192             :             promise_hook_data->before_hook_count);
   18193          45 :       if (promise_hook_data->check_value) {
   18194         150 :         CHECK(
   18195             :             CcTest::global()
   18196             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18197             :                 .ToLocalChecked()
   18198             :                 ->Equals(CcTest::isolate()->GetCurrentContext(),
   18199             :                          v8_str(promise_hook_data->promise_hook_value.c_str()))
   18200             :                 .FromJust());
   18201             :       }
   18202          45 :       SetPromise("after", promise);
   18203          45 :       break;
   18204             :   }
   18205         285 : }
   18206             : 
   18207       23723 : TEST(PromiseHook) {
   18208           5 :   LocalContext env;
   18209           5 :   v8::Isolate* isolate = env->GetIsolate();
   18210          10 :   v8::HandleScope scope(isolate);
   18211             : 
   18212           5 :   v8::Local<v8::Object> global = CcTest::global();
   18213           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   18214             : 
   18215          10 :   promise_hook_data = new PromiseHookData();
   18216           5 :   isolate->SetPromiseHook(CustomPromiseHook);
   18217             : 
   18218             :   // Test that an initialized promise is passed to init. Other hooks
   18219             :   // can not have un initialized promise.
   18220           5 :   promise_hook_data->check_value = false;
   18221             :   CompileRun("var p = new Promise(() => {});");
   18222             : 
   18223          15 :   auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18224          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18225             :   auto init_promise_obj = v8::Local<v8::Promise>::Cast(init_promise);
   18226           5 :   CHECK_EQ(init_promise_obj->State(), v8::Promise::PromiseState::kPending);
   18227           5 :   CHECK(!init_promise_obj->HasHandler());
   18228             : 
   18229           5 :   promise_hook_data->Reset();
   18230           5 :   promise_hook_data->promise_hook_value = "fulfilled";
   18231             :   const char* source =
   18232             :       "var resolve, value = ''; \n"
   18233             :       "var p = new Promise(r => resolve = r); \n";
   18234             : 
   18235             :   CompileRun(source);
   18236          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18237          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18238           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18239           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18240             : 
   18241             :   CompileRun("var p1 = p.then(() => { value = 'fulfilled'; }); \n");
   18242          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18243          15 :   auto parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18244          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   18245          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   18246           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18247           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   18248             : 
   18249             :   CompileRun("resolve(); \n");
   18250             :   auto resolve_promise =
   18251          15 :       global->Get(context, v8_str("resolve")).ToLocalChecked();
   18252          15 :   auto before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18253          15 :   auto after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18254          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18255          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18256          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18257           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18258             : 
   18259             :   CompileRun("value = ''; var p2 = p1.then(() => { value = 'fulfilled' }); \n");
   18260          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18261          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18262          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18263          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18264          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18265          15 :   CHECK(GetPromise("p2")->Equals(env.local(), init_promise).FromJust());
   18266          15 :   CHECK(GetPromise("p1")->Equals(env.local(), parent_promise).FromJust());
   18267          15 :   CHECK(GetPromise("p2")->Equals(env.local(), before_promise).FromJust());
   18268          15 :   CHECK(GetPromise("p2")->Equals(env.local(), after_promise).FromJust());
   18269          15 :   CHECK(GetPromise("p2")->Equals(env.local(), resolve_promise).FromJust());
   18270           5 :   CHECK_EQ(10, promise_hook_data->promise_hook_count);
   18271             : 
   18272             :   promise_hook_data->Reset();
   18273           5 :   promise_hook_data->promise_hook_value = "rejected";
   18274             :   source =
   18275             :       "var reject, value = ''; \n"
   18276             :       "var p = new Promise((_, r) => reject = r); \n";
   18277             : 
   18278             :   CompileRun(source);
   18279          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18280          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18281           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18282           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18283             : 
   18284             :   CompileRun("var p1 = p.catch(() => { value = 'rejected'; }); \n");
   18285          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18286          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18287          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   18288          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   18289           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18290           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   18291             : 
   18292             :   CompileRun("reject(); \n");
   18293          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18294          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18295          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18296          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18297          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18298          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18299           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18300             : 
   18301             :   promise_hook_data->Reset();
   18302           5 :   promise_hook_data->promise_hook_value = "Promise.resolve";
   18303             :   source =
   18304             :       "var value = ''; \n"
   18305             :       "var p = Promise.resolve('Promise.resolve'); \n";
   18306             : 
   18307             :   CompileRun(source);
   18308          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18309          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18310             :   // init hook and resolve hook
   18311           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18312           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18313          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18314          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   18315             : 
   18316             :   CompileRun("var p1 = p.then((v) => { value = v; }); \n");
   18317          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18318          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18319          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18320          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18321          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18322          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   18323          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18324          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   18325          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18326          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18327           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18328           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   18329             : 
   18330             :   promise_hook_data->Reset();
   18331             :   source =
   18332             :       "var resolve, value = ''; \n"
   18333             :       "var p = new Promise((_, r) => resolve = r); \n";
   18334             : 
   18335             :   CompileRun(source);
   18336          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18337          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18338           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18339           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18340             : 
   18341             :   CompileRun("resolve(); \n");
   18342          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18343          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   18344           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18345             : 
   18346             :   promise_hook_data->Reset();
   18347             :   source =
   18348             :       "var reject, value = ''; \n"
   18349             :       "var p = new Promise((_, r) => reject = r); \n";
   18350             : 
   18351             :   CompileRun(source);
   18352          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18353          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18354           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18355           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18356             : 
   18357             :   CompileRun("reject(); \n");
   18358          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18359          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   18360           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18361             : 
   18362             :   promise_hook_data->Reset();
   18363             :   // This test triggers after callbacks right after each other, so
   18364             :   // lets just check the value at the end.
   18365           5 :   promise_hook_data->check_value = false;
   18366           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   18367             :   source =
   18368             :       "var resolve, value = ''; \n"
   18369             :       "var tempPromise = new Promise(r => resolve = r); \n"
   18370             :       "var p = Promise.all([tempPromise]);\n "
   18371             :       "var p1 = p.then(v => value = v[0]); \n";
   18372             : 
   18373             :   CompileRun(source);
   18374             :   // 1) init hook (tempPromise)
   18375             :   // 2) init hook (p)
   18376             :   // 3) init hook (throwaway Promise in Promise.all, p)
   18377             :   // 4) init hook (p1, p)
   18378           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   18379           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   18380             : 
   18381           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   18382             :   CompileRun("resolve('Promise.all'); \n");
   18383          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18384          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18385             :   // 5) resolve hook (tempPromise)
   18386             :   // 6) resolve hook (throwaway Promise in Promise.all)
   18387             :   // 6) before hook (throwaway Promise in Promise.all)
   18388             :   // 7) after hook (throwaway Promise in Promise.all)
   18389             :   // 8) before hook (p)
   18390             :   // 9) after hook (p)
   18391             :   // 10) resolve hook (p1)
   18392             :   // 11) before hook (p1)
   18393             :   // 12) after hook (p1)
   18394           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   18395          30 :   CHECK(CcTest::global()
   18396             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18397             :             .ToLocalChecked()
   18398             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   18399             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   18400             :             .FromJust());
   18401             : 
   18402           5 :   promise_hook_data->Reset();
   18403             :   // This test triggers after callbacks right after each other, so
   18404             :   // lets just check the value at the end.
   18405           5 :   promise_hook_data->check_value = false;
   18406           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   18407             :   source =
   18408             :       "var resolve, value = ''; \n"
   18409             :       "var tempPromise = new Promise(r => resolve = r); \n"
   18410             :       "var p = Promise.race([tempPromise]);\n "
   18411             :       "var p1 = p.then(v => value = v); \n";
   18412             : 
   18413             :   CompileRun(source);
   18414             :   // 1) init hook (tempPromise)
   18415             :   // 2) init hook (p)
   18416             :   // 3) init hook (throwaway Promise in Promise.race, p)
   18417             :   // 4) init hook (p1, p)
   18418           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   18419           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   18420             : 
   18421           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   18422             :   CompileRun("resolve('Promise.race'); \n");
   18423          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18424          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18425             :   // 5) resolve hook (tempPromise)
   18426             :   // 6) resolve hook (throwaway Promise in Promise.race)
   18427             :   // 6) before hook (throwaway Promise in Promise.race)
   18428             :   // 7) after hook (throwaway Promise in Promise.race)
   18429             :   // 8) before hook (p)
   18430             :   // 9) after hook (p)
   18431             :   // 10) resolve hook (p1)
   18432             :   // 11) before hook (p1)
   18433             :   // 12) after hook (p1)
   18434           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   18435          30 :   CHECK(CcTest::global()
   18436             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18437             :             .ToLocalChecked()
   18438             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   18439             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   18440             :             .FromJust());
   18441             : 
   18442           5 :   promise_hook_data->Reset();
   18443           5 :   promise_hook_data->promise_hook_value = "subclass";
   18444             :   source =
   18445             :       "var resolve, value = '';\n"
   18446             :       "class MyPromise extends Promise { \n"
   18447             :       "  then(onFulfilled, onRejected) { \n"
   18448             :       "      return super.then(onFulfilled, onRejected); \n"
   18449             :       "  };\n"
   18450             :       "};\n"
   18451             :       "var p = new MyPromise(r => resolve = r);\n";
   18452             : 
   18453             :   CompileRun(source);
   18454             :   // 1) init hook (p)
   18455           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18456             : 
   18457             :   CompileRun("var p1 = p.then(() => value = 'subclass');\n");
   18458             :   // 2) init hook (p1)
   18459           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18460             : 
   18461             :   CompileRun("resolve();\n");
   18462          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18463          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18464          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18465          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18466          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18467          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18468             :   // 3) resolve hook (p)
   18469             :   // 4) before hook (p)
   18470             :   // 5) after hook (p)
   18471             :   // 6) resolve hook (p1)
   18472           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18473             : 
   18474          10 :   delete promise_hook_data;
   18475          10 :   isolate->SetPromiseHook(nullptr);
   18476           5 : }
   18477             : 
   18478          10 : void AnalyzeStackOfDynamicScriptWithSourceURL(
   18479          50 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18480          10 :   v8::HandleScope scope(args.GetIsolate());
   18481             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18482          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18483          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   18484          10 :   v8::Local<v8::String> url = v8_str("source_url");
   18485          40 :   for (int i = 0; i < 3; i++) {
   18486             :     v8::Local<v8::String> name =
   18487          60 :         stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
   18488          30 :     CHECK(!name.IsEmpty());
   18489          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18490          10 :   }
   18491          10 : }
   18492             : 
   18493             : 
   18494       23723 : TEST(DynamicWithSourceURLInStackTrace) {
   18495           5 :   v8::Isolate* isolate = CcTest::isolate();
   18496           5 :   v8::HandleScope scope(isolate);
   18497           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18498             :   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   18499             :              v8::FunctionTemplate::New(
   18500          15 :                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   18501          10 :   LocalContext context(0, templ);
   18502             : 
   18503             :   const char *source =
   18504             :     "function outer() {\n"
   18505             :     "function bar() {\n"
   18506             :     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   18507             :     "}\n"
   18508             :     "function foo() {\n"
   18509             :     "\n"
   18510             :     "  bar();\n"
   18511             :     "}\n"
   18512             :     "foo();\n"
   18513             :     "}\n"
   18514             :     "outer()\n%s";
   18515             : 
   18516             :   i::ScopedVector<char> code(1024);
   18517           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18518          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18519           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   18520          15 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18521           5 : }
   18522             : 
   18523             : 
   18524       23723 : TEST(DynamicWithSourceURLInStackTraceString) {
   18525           5 :   LocalContext context;
   18526          10 :   v8::HandleScope scope(context->GetIsolate());
   18527             : 
   18528             :   const char *source =
   18529             :     "function outer() {\n"
   18530             :     "  function foo() {\n"
   18531             :     "    FAIL.FAIL;\n"
   18532             :     "  }\n"
   18533             :     "  foo();\n"
   18534             :     "}\n"
   18535             :     "outer()\n%s";
   18536             : 
   18537             :   i::ScopedVector<char> code(1024);
   18538           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18539          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18540           5 :   CompileRunWithOrigin(code.start(), "", 0, 0);
   18541           5 :   CHECK(try_catch.HasCaught());
   18542             :   v8::String::Utf8Value stack(
   18543             :       context->GetIsolate(),
   18544          15 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   18545          15 :   CHECK_NOT_NULL(strstr(*stack, "at foo (source_url:3:5)"));
   18546           5 : }
   18547             : 
   18548             : 
   18549       23723 : TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18550           5 :   LocalContext context;
   18551          10 :   v8::HandleScope scope(context->GetIsolate());
   18552             : 
   18553             :   const char *source =
   18554             :     "function outer() {\n"
   18555             :     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   18556             :     "  //# sourceURL=source_url\";\n"
   18557             :     "  eval(scriptContents);\n"
   18558             :     "  foo(); }\n"
   18559             :     "outer();\n"
   18560             :     "//# sourceURL=outer_url";
   18561             : 
   18562          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18563             :   CompileRun(source);
   18564           5 :   CHECK(try_catch.HasCaught());
   18565             : 
   18566           5 :   Local<v8::Message> message = try_catch.Message();
   18567           5 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18568           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18569           5 :                      "source_url"));
   18570           5 : }
   18571             : 
   18572             : 
   18573       23723 : TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18574           5 :   LocalContext context;
   18575          10 :   v8::HandleScope scope(context->GetIsolate());
   18576             : 
   18577             :   const char *source =
   18578             :     "function outer() {\n"
   18579             :     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   18580             :     "  //# sourceURL=source_url\";\n"
   18581             :     "  eval(scriptContents);\n"
   18582             :     "  boo(); }\n"
   18583             :     "outer();\n"
   18584             :     "//# sourceURL=outer_url";
   18585             : 
   18586          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18587             :   CompileRun(source);
   18588           5 :   CHECK(try_catch.HasCaught());
   18589             : 
   18590           5 :   Local<v8::Message> message = try_catch.Message();
   18591           5 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18592           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18593           5 :                      "source_url"));
   18594           5 : }
   18595             : 
   18596             : 
   18597           5 : static void CreateGarbageInOldSpace() {
   18598             :   i::Factory* factory = CcTest::i_isolate()->factory();
   18599           5 :   v8::HandleScope scope(CcTest::isolate());
   18600             :   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   18601        5005 :   for (int i = 0; i < 1000; i++) {
   18602        5000 :     factory->NewFixedArray(1000, i::TENURED);
   18603           5 :   }
   18604           5 : }
   18605             : 
   18606             : 
   18607             : // Test that idle notification can be handled and eventually collects garbage.
   18608       23723 : TEST(TestIdleNotification) {
   18609           5 :   if (!i::FLAG_incremental_marking) return;
   18610             :   ManualGCScope manual_gc_scope;
   18611             :   const intptr_t MB = 1024 * 1024;
   18612             :   const double IdlePauseInSeconds = 1.0;
   18613          10 :   LocalContext env;
   18614          10 :   v8::HandleScope scope(env->GetIsolate());
   18615           5 :   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   18616           5 :   CreateGarbageInOldSpace();
   18617           5 :   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   18618           5 :   CHECK_GT(size_with_garbage, initial_size + MB);
   18619             :   bool finished = false;
   18620          10 :   for (int i = 0; i < 200 && !finished; i++) {
   18621          20 :     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
   18622             :       CcTest::heap()->StartIdleIncrementalMarking(
   18623           5 :           i::GarbageCollectionReason::kTesting);
   18624             :     }
   18625             :     finished = env->GetIsolate()->IdleNotificationDeadline(
   18626          30 :         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   18627             :          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   18628          20 :         IdlePauseInSeconds);
   18629          20 :     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
   18630           5 :       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
   18631             :     }
   18632             :   }
   18633           5 :   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   18634           5 :   CHECK(finished);
   18635           5 :   CHECK_LT(final_size, initial_size + 1);
   18636             : }
   18637             : 
   18638             : 
   18639       23723 : TEST(Regress2333) {
   18640           5 :   LocalContext env;
   18641          20 :   for (int i = 0; i < 3; i++) {
   18642          15 :     CcTest::CollectGarbage(i::NEW_SPACE);
   18643           5 :   }
   18644           5 : }
   18645             : 
   18646             : static uint32_t* stack_limit;
   18647             : 
   18648          10 : static void GetStackLimitCallback(
   18649             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18650             :   stack_limit = reinterpret_cast<uint32_t*>(
   18651          10 :       CcTest::i_isolate()->stack_guard()->real_climit());
   18652          10 : }
   18653             : 
   18654             : 
   18655             : // Uses the address of a local variable to determine the stack top now.
   18656             : // Given a size, returns an address that is that far from the current
   18657             : // top of stack.
   18658             : static uint32_t* ComputeStackLimit(uint32_t size) {
   18659             :   uint32_t* answer = &size - (size / sizeof(size));
   18660             :   // If the size is very large and the stack is very near the bottom of
   18661             :   // memory then the calculation above may wrap around and give an address
   18662             :   // that is above the (downwards-growing) stack.  In that case we return
   18663             :   // a very low address.
   18664             :   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   18665             :   return answer;
   18666             : }
   18667             : 
   18668             : 
   18669             : // We need at least 165kB for an x64 debug build with clang and ASAN.
   18670             : static const int stack_breathing_room = 256 * i::KB;
   18671             : 
   18672             : 
   18673       23723 : TEST(SetStackLimit) {
   18674             :   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   18675             : 
   18676             :   // Set stack limit.
   18677           5 :   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18678             : 
   18679             :   // Execute a script.
   18680           5 :   LocalContext env;
   18681          10 :   v8::HandleScope scope(env->GetIsolate());
   18682             :   Local<v8::FunctionTemplate> fun_templ =
   18683           5 :       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   18684          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18685          25 :   CHECK(env->Global()
   18686             :             ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18687             :             .FromJust());
   18688             :   CompileRun("get_stack_limit();");
   18689             : 
   18690          10 :   CHECK(stack_limit == set_limit);
   18691           5 : }
   18692             : 
   18693             : 
   18694       23723 : TEST(SetStackLimitInThread) {
   18695             :   uint32_t* set_limit;
   18696             :   {
   18697           5 :     v8::Locker locker(CcTest::isolate());
   18698             :     set_limit = ComputeStackLimit(stack_breathing_room);
   18699             : 
   18700             :     // Set stack limit.
   18701           5 :     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18702             : 
   18703             :     // Execute a script.
   18704          10 :     v8::HandleScope scope(CcTest::isolate());
   18705          10 :     LocalContext env;
   18706             :     Local<v8::FunctionTemplate> fun_templ =
   18707           5 :         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   18708          10 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18709          25 :     CHECK(env->Global()
   18710             :               ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18711             :               .FromJust());
   18712             :     CompileRun("get_stack_limit();");
   18713             : 
   18714          10 :     CHECK(stack_limit == set_limit);
   18715             :   }
   18716             :   {
   18717           5 :     v8::Locker locker(CcTest::isolate());
   18718           5 :     CHECK(stack_limit == set_limit);
   18719             :   }
   18720           5 : }
   18721             : 
   18722             : 
   18723       23724 : THREADED_TEST(GetHeapStatistics) {
   18724           6 :   LocalContext c1;
   18725          12 :   v8::HandleScope scope(c1->GetIsolate());
   18726           6 :   v8::HeapStatistics heap_statistics;
   18727           6 :   CHECK_EQ(0u, heap_statistics.total_heap_size());
   18728           6 :   CHECK_EQ(0u, heap_statistics.used_heap_size());
   18729           6 :   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   18730           6 :   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   18731          12 :   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   18732           6 : }
   18733             : 
   18734             : 
   18735             : class VisitorImpl : public v8::ExternalResourceVisitor {
   18736             :  public:
   18737           5 :   explicit VisitorImpl(TestResource** resource) {
   18738          20 :     for (int i = 0; i < 4; i++) {
   18739          20 :       resource_[i] = resource[i];
   18740          20 :       found_resource_[i] = false;
   18741             :     }
   18742             :   }
   18743           5 :   virtual ~VisitorImpl() {}
   18744          70 :   virtual void VisitExternalString(v8::Local<v8::String> string) {
   18745          70 :     if (!string->IsExternal()) {
   18746          50 :       CHECK(string->IsExternalOneByte());
   18747          70 :       return;
   18748             :     }
   18749             :     v8::String::ExternalStringResource* resource =
   18750             :         string->GetExternalStringResource();
   18751          20 :     CHECK(resource);
   18752          80 :     for (int i = 0; i < 4; i++) {
   18753          80 :       if (resource_[i] == resource) {
   18754          20 :         CHECK(!found_resource_[i]);
   18755          20 :         found_resource_[i] = true;
   18756             :       }
   18757             :     }
   18758             :   }
   18759           5 :   void CheckVisitedResources() {
   18760          25 :     for (int i = 0; i < 4; i++) {
   18761          20 :       CHECK(found_resource_[i]);
   18762             :     }
   18763           5 :   }
   18764             : 
   18765             :  private:
   18766             :   v8::String::ExternalStringResource* resource_[4];
   18767             :   bool found_resource_[4];
   18768             : };
   18769             : 
   18770             : 
   18771       23723 : TEST(ExternalizeOldSpaceTwoByteCons) {
   18772           5 :   v8::Isolate* isolate = CcTest::isolate();
   18773           5 :   LocalContext env;
   18774          10 :   v8::HandleScope scope(isolate);
   18775             :   v8::Local<v8::String> cons =
   18776             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18777           5 :           ->ToString(env.local())
   18778           5 :           .ToLocalChecked();
   18779           5 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18780           5 :   CcTest::CollectAllAvailableGarbage();
   18781           5 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18782             : 
   18783             :   TestResource* resource = new TestResource(
   18784           5 :       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   18785           5 :   cons->MakeExternal(resource);
   18786             : 
   18787           5 :   CHECK(cons->IsExternal());
   18788           5 :   CHECK_EQ(resource, cons->GetExternalStringResource());
   18789             :   String::Encoding encoding;
   18790           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18791          10 :   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   18792           5 : }
   18793             : 
   18794             : 
   18795       23723 : TEST(ExternalizeOldSpaceOneByteCons) {
   18796           5 :   v8::Isolate* isolate = CcTest::isolate();
   18797           5 :   LocalContext env;
   18798          10 :   v8::HandleScope scope(isolate);
   18799             :   v8::Local<v8::String> cons =
   18800             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18801           5 :           ->ToString(env.local())
   18802           5 :           .ToLocalChecked();
   18803           5 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18804           5 :   CcTest::CollectAllAvailableGarbage();
   18805           5 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18806             : 
   18807             :   TestOneByteResource* resource =
   18808           5 :       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   18809           5 :   cons->MakeExternal(resource);
   18810             : 
   18811           5 :   CHECK(cons->IsExternalOneByte());
   18812           5 :   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   18813             :   String::Encoding encoding;
   18814           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18815          10 :   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   18816           5 : }
   18817             : 
   18818             : 
   18819       23723 : TEST(VisitExternalStrings) {
   18820           5 :   v8::Isolate* isolate = CcTest::isolate();
   18821           5 :   LocalContext env;
   18822          10 :   v8::HandleScope scope(isolate);
   18823             :   const char* string = "Some string";
   18824           5 :   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   18825             :   TestResource* resource[4];
   18826          10 :   resource[0] = new TestResource(two_byte_string);
   18827             :   v8::Local<v8::String> string0 =
   18828           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
   18829           5 :           .ToLocalChecked();
   18830          10 :   resource[1] = new TestResource(two_byte_string, nullptr, false);
   18831             :   v8::Local<v8::String> string1 =
   18832           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
   18833           5 :           .ToLocalChecked();
   18834             : 
   18835             :   // Externalized symbol.
   18836          10 :   resource[2] = new TestResource(two_byte_string, nullptr, false);
   18837             :   v8::Local<v8::String> string2 =
   18838             :       v8::String::NewFromUtf8(env->GetIsolate(), string,
   18839           5 :                               v8::NewStringType::kInternalized)
   18840           5 :           .ToLocalChecked();
   18841           5 :   CHECK(string2->MakeExternal(resource[2]));
   18842             : 
   18843             :   // Symbolized External.
   18844          10 :   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   18845             :   v8::Local<v8::String> string3 =
   18846           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
   18847           5 :           .ToLocalChecked();
   18848           5 :   CcTest::CollectAllAvailableGarbage();  // Tenure string.
   18849             :   // Turn into a symbol.
   18850             :   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   18851          10 :   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   18852             :       string3_i).is_null());
   18853           5 :   CHECK(string3_i->IsInternalizedString());
   18854             : 
   18855             :   // We need to add usages for string* to avoid warnings in GCC 4.7
   18856           5 :   CHECK(string0->IsExternal());
   18857           5 :   CHECK(string1->IsExternal());
   18858           5 :   CHECK(string2->IsExternal());
   18859           5 :   CHECK(string3->IsExternal());
   18860             : 
   18861             :   VisitorImpl visitor(resource);
   18862           5 :   isolate->VisitExternalResources(&visitor);
   18863          10 :   visitor.CheckVisitedResources();
   18864           5 : }
   18865             : 
   18866             : 
   18867       23723 : TEST(ExternalStringCollectedAtTearDown) {
   18868           5 :   int destroyed = 0;
   18869             :   v8::Isolate::CreateParams create_params;
   18870           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18871           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18872             :   { v8::Isolate::Scope isolate_scope(isolate);
   18873          10 :     v8::HandleScope handle_scope(isolate);
   18874             :     const char* s = "One string to test them all, one string to find them.";
   18875             :     TestOneByteResource* inscription =
   18876           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18877             :     v8::Local<v8::String> ring =
   18878           5 :         v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
   18879             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18880           5 :     CHECK_EQ(0, destroyed);
   18881             :     USE(ring);
   18882             :   }
   18883             : 
   18884           5 :   isolate->Dispose();
   18885             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18886           5 :   CHECK_EQ(1, destroyed);
   18887           5 : }
   18888             : 
   18889             : 
   18890       23723 : TEST(ExternalInternalizedStringCollectedAtTearDown) {
   18891           5 :   int destroyed = 0;
   18892             :   v8::Isolate::CreateParams create_params;
   18893           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18894           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18895             :   { v8::Isolate::Scope isolate_scope(isolate);
   18896           5 :     LocalContext env(isolate);
   18897          10 :     v8::HandleScope handle_scope(isolate);
   18898             :     CompileRun("var ring = 'One string to test them all';");
   18899             :     const char* s = "One string to test them all";
   18900             :     TestOneByteResource* inscription =
   18901           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18902             :     v8::Local<v8::String> ring =
   18903          10 :         CompileRun("ring")->ToString(env.local()).ToLocalChecked();
   18904           5 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18905           5 :     ring->MakeExternal(inscription);
   18906             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18907           5 :     CHECK_EQ(0, destroyed);
   18908             :     USE(ring);
   18909             :   }
   18910             : 
   18911           5 :   isolate->Dispose();
   18912             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18913           5 :   CHECK_EQ(1, destroyed);
   18914           5 : }
   18915             : 
   18916             : 
   18917       23723 : TEST(ExternalInternalizedStringCollectedAtGC) {
   18918           5 :   int destroyed = 0;
   18919           5 :   { LocalContext env;
   18920          10 :     v8::HandleScope handle_scope(env->GetIsolate());
   18921             :     CompileRun("var ring = 'One string to test them all';");
   18922             :     const char* s = "One string to test them all";
   18923             :     TestOneByteResource* inscription =
   18924           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18925             :     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
   18926           5 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18927           5 :     ring->MakeExternal(inscription);
   18928             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18929           5 :     CHECK_EQ(0, destroyed);
   18930           5 :     USE(ring);
   18931             :   }
   18932             : 
   18933             :   // Garbage collector deals swift blows to evil.
   18934           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
   18935           5 :   CcTest::CollectAllAvailableGarbage();
   18936             : 
   18937             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18938           5 :   CHECK_EQ(1, destroyed);
   18939           5 : }
   18940             : 
   18941             : 
   18942             : static double DoubleFromBits(uint64_t value) {
   18943             :   double target;
   18944             :   i::MemCopy(&target, &value, sizeof(target));
   18945             :   return target;
   18946             : }
   18947             : 
   18948             : 
   18949             : static uint64_t DoubleToBits(double value) {
   18950             :   uint64_t target;
   18951             :   i::MemCopy(&target, &value, sizeof(target));
   18952             :   return target;
   18953             : }
   18954             : 
   18955             : 
   18956         120 : static double DoubleToDateTime(double input) {
   18957             :   double date_limit = 864e13;
   18958         120 :   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   18959             :     return std::numeric_limits<double>::quiet_NaN();
   18960             :   }
   18961          60 :   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   18962             : }
   18963             : 
   18964             : 
   18965             : // We don't have a consistent way to write 64-bit constants syntactically, so we
   18966             : // split them into two 32-bit constants and combine them programmatically.
   18967             : static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   18968             :   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   18969             : }
   18970             : 
   18971             : 
   18972       23724 : THREADED_TEST(QuietSignalingNaNs) {
   18973           6 :   LocalContext context;
   18974           6 :   v8::Isolate* isolate = context->GetIsolate();
   18975          12 :   v8::HandleScope scope(isolate);
   18976          12 :   v8::TryCatch try_catch(isolate);
   18977             : 
   18978             :   // Special double values.
   18979             :   double snan = DoubleFromBits(0x7ff00000, 0x00000001);
   18980             :   double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
   18981             :   double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
   18982             :   double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
   18983             :   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   18984             :   double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
   18985             :   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   18986             : 
   18987             :   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   18988             :   // on either side of the epoch.
   18989             :   double date_limit = 864e13;
   18990             : 
   18991             :   double test_values[] = {
   18992             :       snan,
   18993             :       qnan,
   18994             :       infinity,
   18995             :       max_normal,
   18996             :       date_limit + 1,
   18997             :       date_limit,
   18998             :       min_normal,
   18999             :       max_denormal,
   19000             :       min_denormal,
   19001             :       0,
   19002             :       -0,
   19003             :       -min_denormal,
   19004             :       -max_denormal,
   19005             :       -min_normal,
   19006             :       -date_limit,
   19007             :       -date_limit - 1,
   19008             :       -max_normal,
   19009             :       -infinity,
   19010             :       -qnan,
   19011             :       -snan
   19012           6 :   };
   19013             :   int num_test_values = 20;
   19014             : 
   19015         126 :   for (int i = 0; i < num_test_values; i++) {
   19016         120 :     double test_value = test_values[i];
   19017             : 
   19018             :     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   19019         120 :     v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
   19020         240 :     double stored_number = number->NumberValue(context.local()).FromJust();
   19021         120 :     if (!std::isnan(test_value)) {
   19022          96 :       CHECK_EQ(test_value, stored_number);
   19023             :     } else {
   19024             :       uint64_t stored_bits = DoubleToBits(stored_number);
   19025             :       // Check if quiet nan (bits 51..62 all set).
   19026             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   19027             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   19028             :     !defined(USE_SIMULATOR)
   19029             :       // Most significant fraction bit for quiet nan is set to 0
   19030             :       // on MIPS architecture. Allowed by IEEE-754.
   19031             :       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   19032             : #else
   19033          24 :       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   19034             : #endif
   19035             :     }
   19036             : 
   19037             :     // Check that Date::New preserves non-NaNs in the date range and
   19038             :     // quiets SNaNs.
   19039             :     v8::Local<v8::Value> date =
   19040         120 :         v8::Date::New(context.local(), test_value).ToLocalChecked();
   19041         120 :     double expected_stored_date = DoubleToDateTime(test_value);
   19042         240 :     double stored_date = date->NumberValue(context.local()).FromJust();
   19043         120 :     if (!std::isnan(expected_stored_date)) {
   19044          60 :       CHECK_EQ(expected_stored_date, stored_date);
   19045             :     } else {
   19046             :       uint64_t stored_bits = DoubleToBits(stored_date);
   19047             :       // Check if quiet nan (bits 51..62 all set).
   19048             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   19049             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   19050             :     !defined(USE_SIMULATOR)
   19051             :       // Most significant fraction bit for quiet nan is set to 0
   19052             :       // on MIPS architecture. Allowed by IEEE-754.
   19053             :       CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
   19054             : #else
   19055          60 :       CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
   19056             : #endif
   19057             :     }
   19058           6 :   }
   19059           6 : }
   19060             : 
   19061             : 
   19062          66 : static void SpaghettiIncident(
   19063         198 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   19064          66 :   v8::HandleScope scope(args.GetIsolate());
   19065         132 :   v8::TryCatch tc(args.GetIsolate());
   19066             :   v8::MaybeLocal<v8::String> str(
   19067         132 :       args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
   19068             :   USE(str);
   19069          66 :   if (tc.HasCaught())
   19070         132 :     tc.ReThrow();
   19071          66 : }
   19072             : 
   19073             : 
   19074             : // Test that an exception can be propagated down through a spaghetti
   19075             : // stack using ReThrow.
   19076       23724 : THREADED_TEST(SpaghettiStackReThrow) {
   19077           6 :   v8::Isolate* isolate = CcTest::isolate();
   19078           6 :   v8::HandleScope scope(isolate);
   19079          12 :   LocalContext context;
   19080             :   context->Global()
   19081             :       ->Set(context.local(), v8_str("s"),
   19082           6 :             v8::FunctionTemplate::New(isolate, SpaghettiIncident)
   19083          18 :                 ->GetFunction(context.local())
   19084          30 :                 .ToLocalChecked())
   19085          12 :       .FromJust();
   19086          12 :   v8::TryCatch try_catch(isolate);
   19087             :   CompileRun(
   19088             :       "var i = 0;"
   19089             :       "var o = {"
   19090             :       "  toString: function () {"
   19091             :       "    if (i == 10) {"
   19092             :       "      throw 'Hey!';"
   19093             :       "    } else {"
   19094             :       "      i++;"
   19095             :       "      return s(o);"
   19096             :       "    }"
   19097             :       "  }"
   19098             :       "};"
   19099             :       "s(o);");
   19100           6 :   CHECK(try_catch.HasCaught());
   19101          12 :   v8::String::Utf8Value value(isolate, try_catch.Exception());
   19102          12 :   CHECK_EQ(0, strcmp(*value, "Hey!"));
   19103           6 : }
   19104             : 
   19105             : 
   19106       23723 : TEST(Regress528) {
   19107             :   ManualGCScope manual_gc_scope;
   19108           5 :   v8::V8::Initialize();
   19109           5 :   v8::Isolate* isolate = CcTest::isolate();
   19110           5 :   i::FLAG_retain_maps_for_n_gc = 0;
   19111          10 :   v8::HandleScope scope(isolate);
   19112             :   v8::Local<Context> other_context;
   19113             :   int gc_count;
   19114             : 
   19115             :   // Create a context used to keep the code from aging in the compilation
   19116             :   // cache.
   19117           5 :   other_context = Context::New(isolate);
   19118             : 
   19119             :   // Context-dependent context data creates reference from the compilation
   19120             :   // cache to the global object.
   19121             :   const char* source_simple = "1";
   19122             :   {
   19123           5 :     v8::HandleScope scope(isolate);
   19124           5 :     v8::Local<Context> context = Context::New(isolate);
   19125             : 
   19126           5 :     context->Enter();
   19127           5 :     Local<v8::String> obj = v8_str("");
   19128           5 :     context->SetEmbedderData(0, obj);
   19129             :     CompileRun(source_simple);
   19130           5 :     context->Exit();
   19131             :   }
   19132           5 :   isolate->ContextDisposedNotification();
   19133           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   19134           5 :     other_context->Enter();
   19135             :     CompileRun(source_simple);
   19136           5 :     other_context->Exit();
   19137           5 :     CcTest::CollectAllGarbage();
   19138           5 :     if (GetGlobalObjectsCount() == 1) break;
   19139             :   }
   19140           5 :   CHECK_GE(2, gc_count);
   19141           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   19142             : 
   19143             :   // Eval in a function creates reference from the compilation cache to the
   19144             :   // global object.
   19145             :   const char* source_eval = "function f(){eval('1')}; f()";
   19146             :   {
   19147           5 :     v8::HandleScope scope(isolate);
   19148           5 :     v8::Local<Context> context = Context::New(isolate);
   19149             : 
   19150           5 :     context->Enter();
   19151             :     CompileRun(source_eval);
   19152           5 :     context->Exit();
   19153             :   }
   19154           5 :   isolate->ContextDisposedNotification();
   19155           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   19156           5 :     other_context->Enter();
   19157             :     CompileRun(source_eval);
   19158           5 :     other_context->Exit();
   19159           5 :     CcTest::CollectAllGarbage();
   19160           5 :     if (GetGlobalObjectsCount() == 1) break;
   19161             :   }
   19162           5 :   CHECK_GE(2, gc_count);
   19163           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   19164             : 
   19165             :   // Looking up the line number for an exception creates reference from the
   19166             :   // compilation cache to the global object.
   19167             :   const char* source_exception = "function f(){throw 1;} f()";
   19168             :   {
   19169           5 :     v8::HandleScope scope(isolate);
   19170           5 :     v8::Local<Context> context = Context::New(isolate);
   19171             : 
   19172           5 :     context->Enter();
   19173          10 :     v8::TryCatch try_catch(isolate);
   19174             :     CompileRun(source_exception);
   19175           5 :     CHECK(try_catch.HasCaught());
   19176           5 :     v8::Local<v8::Message> message = try_catch.Message();
   19177           5 :     CHECK(!message.IsEmpty());
   19178          10 :     CHECK_EQ(1, message->GetLineNumber(context).FromJust());
   19179          10 :     context->Exit();
   19180             :   }
   19181           5 :   isolate->ContextDisposedNotification();
   19182           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   19183           5 :     other_context->Enter();
   19184             :     CompileRun(source_exception);
   19185           5 :     other_context->Exit();
   19186           5 :     CcTest::CollectAllGarbage();
   19187           5 :     if (GetGlobalObjectsCount() == 1) break;
   19188             :   }
   19189           5 :   CHECK_GE(2, gc_count);
   19190           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   19191             : 
   19192           5 :   isolate->ContextDisposedNotification();
   19193           5 : }
   19194             : 
   19195             : 
   19196       23724 : THREADED_TEST(ScriptOrigin) {
   19197           6 :   LocalContext env;
   19198           6 :   v8::Isolate* isolate = env->GetIsolate();
   19199          12 :   v8::HandleScope scope(isolate);
   19200           6 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 1));
   19201           6 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   19202           6 :   array->Set(0, symbol);
   19203             : 
   19204             :   v8::ScriptOrigin origin = v8::ScriptOrigin(
   19205             :       v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
   19206             :       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
   19207             :       v8::Local<v8::Integer>(), v8_str("http://sourceMapUrl"),
   19208             :       v8::True(env->GetIsolate()), v8::False(env->GetIsolate()),
   19209          42 :       v8::False(env->GetIsolate()), array);
   19210           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   19211           6 :   v8::Script::Compile(env.local(), script, &origin)
   19212           6 :       .ToLocalChecked()
   19213           6 :       ->Run(env.local())
   19214           6 :       .ToLocalChecked();
   19215             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19216          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19217             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19218          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19219             : 
   19220           6 :   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   19221           6 :   CHECK_EQ(0, strcmp("test",
   19222             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19223             :                                             script_origin_f.ResourceName())));
   19224          12 :   CHECK_EQ(
   19225             :       1,
   19226             :       script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   19227           6 :   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
   19228           6 :   CHECK(script_origin_f.Options().IsOpaque());
   19229           6 :   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
   19230          12 :   CHECK(script_origin_f.HostDefinedOptions()->Get(0)->IsSymbol());
   19231             : 
   19232           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   19233             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19234             :                                             script_origin_f.SourceMapUrl())));
   19235             : 
   19236           6 :   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   19237           6 :   CHECK_EQ(0, strcmp("test",
   19238             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19239             :                                             script_origin_g.ResourceName())));
   19240          12 :   CHECK_EQ(
   19241             :       1,
   19242             :       script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   19243           6 :   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
   19244           6 :   CHECK(script_origin_g.Options().IsOpaque());
   19245           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   19246             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19247             :                                             script_origin_g.SourceMapUrl())));
   19248          18 :   CHECK(script_origin_g.HostDefinedOptions()->Get(0)->IsSymbol());
   19249           6 : }
   19250             : 
   19251             : 
   19252       23724 : THREADED_TEST(FunctionGetInferredName) {
   19253           6 :   LocalContext env;
   19254          12 :   v8::HandleScope scope(env->GetIsolate());
   19255           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19256             :   v8::Local<v8::String> script =
   19257           6 :       v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   19258           6 :   v8::Script::Compile(env.local(), script, &origin)
   19259           6 :       .ToLocalChecked()
   19260           6 :       ->Run(env.local())
   19261           6 :       .ToLocalChecked();
   19262             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19263          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19264          12 :   CHECK_EQ(0,
   19265             :            strcmp("foo.bar.baz", *v8::String::Utf8Value(env->GetIsolate(),
   19266           6 :                                                         f->GetInferredName())));
   19267           6 : }
   19268             : 
   19269             : 
   19270       23724 : THREADED_TEST(FunctionGetDebugName) {
   19271           6 :   LocalContext env;
   19272          12 :   v8::HandleScope scope(env->GetIsolate());
   19273             :   const char* code =
   19274             :       "var error = false;"
   19275             :       "function a() { this.x = 1; };"
   19276             :       "a.displayName = 'display_a';"
   19277             :       "var b = (function() {"
   19278             :       "  var f = function() { this.x = 2; };"
   19279             :       "  f.displayName = 'display_b';"
   19280             :       "  return f;"
   19281             :       "})();"
   19282             :       "var c = function() {};"
   19283             :       "c.__defineGetter__('displayName', function() {"
   19284             :       "  error = true;"
   19285             :       "  throw new Error();"
   19286             :       "});"
   19287             :       "function d() {};"
   19288             :       "d.__defineGetter__('displayName', function() {"
   19289             :       "  error = true;"
   19290             :       "  return 'wrong_display_name';"
   19291             :       "});"
   19292             :       "function e() {};"
   19293             :       "e.displayName = 'wrong_display_name';"
   19294             :       "e.__defineSetter__('displayName', function() {"
   19295             :       "  error = true;"
   19296             :       "  throw new Error();"
   19297             :       "});"
   19298             :       "function f() {};"
   19299             :       "f.displayName = { 'foo': 6, toString: function() {"
   19300             :       "  error = true;"
   19301             :       "  return 'wrong_display_name';"
   19302             :       "}};"
   19303             :       "var g = function() {"
   19304             :       "  arguments.callee.displayName = 'set_in_runtime';"
   19305             :       "}; g();"
   19306             :       "var h = function() {};"
   19307             :       "h.displayName = 'displayName';"
   19308             :       "Object.defineProperty(h, 'name', { value: 'function.name' });"
   19309             :       "var i = function() {};"
   19310             :       "i.displayName = 239;"
   19311             :       "Object.defineProperty(i, 'name', { value: 'function.name' });"
   19312             :       "var j = function() {};"
   19313             :       "Object.defineProperty(j, 'name', { value: 'function.name' });"
   19314             :       "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
   19315             :       "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
   19316           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19317           6 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19318           6 :       .ToLocalChecked()
   19319           6 :       ->Run(env.local())
   19320           6 :       .ToLocalChecked();
   19321             :   v8::Local<v8::Value> error =
   19322          30 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19323          12 :   CHECK(!error->BooleanValue(env.local()).FromJust());
   19324             :   const char* functions[] = {"a", "display_a",
   19325             :                              "b", "display_b",
   19326             :                              "c", "c",
   19327             :                              "d", "d",
   19328             :                              "e", "e",
   19329             :                              "f", "f",
   19330             :                              "g", "set_in_runtime",
   19331             :                              "h", "displayName",
   19332             :                              "i", "function.name",
   19333             :                              "j", "function.name",
   19334             :                              "k", "foo.bar.baz",
   19335           6 :                              "l", "baz"};
   19336          78 :   for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
   19337             :     v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19338             :         env->Global()
   19339             :             ->Get(env.local(),
   19340          72 :                   v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
   19341         144 :                                           v8::NewStringType::kNormal)
   19342         288 :                       .ToLocalChecked())
   19343          72 :             .ToLocalChecked());
   19344         144 :     CHECK_EQ(0, strcmp(functions[i * 2 + 1],
   19345             :                        *v8::String::Utf8Value(env->GetIsolate(),
   19346             :                                               f->GetDebugName())));
   19347           6 :   }
   19348           6 : }
   19349             : 
   19350             : 
   19351       23724 : THREADED_TEST(FunctionGetDisplayName) {
   19352           6 :   LocalContext env;
   19353          12 :   v8::HandleScope scope(env->GetIsolate());
   19354             :   const char* code = "var error = false;"
   19355             :                      "function a() { this.x = 1; };"
   19356             :                      "a.displayName = 'display_a';"
   19357             :                      "var b = (function() {"
   19358             :                      "  var f = function() { this.x = 2; };"
   19359             :                      "  f.displayName = 'display_b';"
   19360             :                      "  return f;"
   19361             :                      "})();"
   19362             :                      "var c = function() {};"
   19363             :                      "c.__defineGetter__('displayName', function() {"
   19364             :                      "  error = true;"
   19365             :                      "  throw new Error();"
   19366             :                      "});"
   19367             :                      "function d() {};"
   19368             :                      "d.__defineGetter__('displayName', function() {"
   19369             :                      "  error = true;"
   19370             :                      "  return 'wrong_display_name';"
   19371             :                      "});"
   19372             :                      "function e() {};"
   19373             :                      "e.displayName = 'wrong_display_name';"
   19374             :                      "e.__defineSetter__('displayName', function() {"
   19375             :                      "  error = true;"
   19376             :                      "  throw new Error();"
   19377             :                      "});"
   19378             :                      "function f() {};"
   19379             :                      "f.displayName = { 'foo': 6, toString: function() {"
   19380             :                      "  error = true;"
   19381             :                      "  return 'wrong_display_name';"
   19382             :                      "}};"
   19383             :                      "var g = function() {"
   19384             :                      "  arguments.callee.displayName = 'set_in_runtime';"
   19385             :                      "}; g();";
   19386           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19387           6 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19388           6 :       .ToLocalChecked()
   19389           6 :       ->Run(env.local())
   19390           6 :       .ToLocalChecked();
   19391             :   v8::Local<v8::Value> error =
   19392          30 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19393             :   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   19394          30 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   19395             :   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   19396          30 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   19397             :   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   19398          30 :       env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
   19399             :   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   19400          30 :       env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
   19401             :   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   19402          30 :       env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
   19403             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19404          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19405             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19406          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19407          12 :   CHECK(!error->BooleanValue(env.local()).FromJust());
   19408          12 :   CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(env->GetIsolate(),
   19409             :                                                          a->GetDisplayName())));
   19410          12 :   CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(env->GetIsolate(),
   19411             :                                                          b->GetDisplayName())));
   19412          12 :   CHECK(c->GetDisplayName()->IsUndefined());
   19413          12 :   CHECK(d->GetDisplayName()->IsUndefined());
   19414          12 :   CHECK(e->GetDisplayName()->IsUndefined());
   19415          12 :   CHECK(f->GetDisplayName()->IsUndefined());
   19416          12 :   CHECK_EQ(
   19417             :       0, strcmp("set_in_runtime", *v8::String::Utf8Value(env->GetIsolate(),
   19418           6 :                                                          g->GetDisplayName())));
   19419           6 : }
   19420             : 
   19421             : 
   19422       23724 : THREADED_TEST(ScriptLineNumber) {
   19423           6 :   LocalContext env;
   19424          12 :   v8::HandleScope scope(env->GetIsolate());
   19425           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19426           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   19427           6 :   v8::Script::Compile(env.local(), script, &origin)
   19428           6 :       .ToLocalChecked()
   19429           6 :       ->Run(env.local())
   19430           6 :       .ToLocalChecked();
   19431             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19432          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19433             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19434          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19435           6 :   CHECK_EQ(0, f->GetScriptLineNumber());
   19436          12 :   CHECK_EQ(2, g->GetScriptLineNumber());
   19437           6 : }
   19438             : 
   19439             : 
   19440       23724 : THREADED_TEST(ScriptColumnNumber) {
   19441           6 :   LocalContext env;
   19442           6 :   v8::Isolate* isolate = env->GetIsolate();
   19443          12 :   v8::HandleScope scope(isolate);
   19444             :   v8::ScriptOrigin origin =
   19445             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19446           6 :                        v8::Integer::New(isolate, 2));
   19447             :   v8::Local<v8::String> script =
   19448           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19449           6 :   v8::Script::Compile(env.local(), script, &origin)
   19450           6 :       .ToLocalChecked()
   19451           6 :       ->Run(env.local())
   19452           6 :       .ToLocalChecked();
   19453             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19454          30 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19455             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19456          30 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19457           6 :   CHECK_EQ(14, foo->GetScriptColumnNumber());
   19458          12 :   CHECK_EQ(17, bar->GetScriptColumnNumber());
   19459           6 : }
   19460             : 
   19461             : 
   19462       23724 : THREADED_TEST(FunctionGetScriptId) {
   19463           6 :   LocalContext env;
   19464           6 :   v8::Isolate* isolate = env->GetIsolate();
   19465          12 :   v8::HandleScope scope(isolate);
   19466             :   v8::ScriptOrigin origin =
   19467             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19468           6 :                        v8::Integer::New(isolate, 2));
   19469             :   v8::Local<v8::String> scriptSource =
   19470           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19471             :   v8::Local<v8::Script> script(
   19472           6 :       v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
   19473           6 :   script->Run(env.local()).ToLocalChecked();
   19474             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19475          30 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19476             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19477          30 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19478          12 :   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   19479          18 :   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   19480           6 : }
   19481             : 
   19482             : 
   19483       23724 : THREADED_TEST(FunctionGetBoundFunction) {
   19484           6 :   LocalContext env;
   19485          12 :   v8::HandleScope scope(env->GetIsolate());
   19486           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19487             :   v8::Local<v8::String> script = v8_str(
   19488             :       "var a = new Object();\n"
   19489             :       "a.x = 1;\n"
   19490             :       "function f () { return this.x };\n"
   19491             :       "var g = f.bind(a);\n"
   19492           6 :       "var b = g();");
   19493           6 :   v8::Script::Compile(env.local(), script, &origin)
   19494           6 :       .ToLocalChecked()
   19495           6 :       ->Run(env.local())
   19496           6 :       .ToLocalChecked();
   19497             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19498          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19499             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19500          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19501          12 :   CHECK(g->GetBoundFunction()->IsFunction());
   19502             :   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   19503           6 :       g->GetBoundFunction());
   19504          18 :   CHECK(f->GetName()
   19505             :             ->Equals(env.local(), original_function->GetName())
   19506             :             .FromJust());
   19507           6 :   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   19508           6 :   CHECK_EQ(f->GetScriptColumnNumber(),
   19509           6 :            original_function->GetScriptColumnNumber());
   19510           6 : }
   19511             : 
   19512             : 
   19513         330 : static void GetterWhichReturns42(
   19514             :     Local<String> name,
   19515             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19516         330 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19517         330 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19518         330 :   info.GetReturnValue().Set(v8_num(42));
   19519         330 : }
   19520             : 
   19521             : 
   19522         270 : static void SetterWhichSetsYOnThisTo23(
   19523             :     Local<String> name,
   19524             :     Local<Value> value,
   19525             :     const v8::PropertyCallbackInfo<void>& info) {
   19526         270 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19527         270 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19528             :   Local<Object>::Cast(info.This())
   19529         810 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19530         540 :       .FromJust();
   19531         270 : }
   19532             : 
   19533             : 
   19534         120 : void FooGetInterceptor(Local<Name> name,
   19535             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19536         120 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19537         120 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19538         360 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19539         240 :            .FromJust()) {
   19540         120 :     return;
   19541             :   }
   19542          96 :   info.GetReturnValue().Set(v8_num(42));
   19543             : }
   19544             : 
   19545             : 
   19546         336 : void FooSetInterceptor(Local<Name> name, Local<Value> value,
   19547             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19548         336 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19549         336 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19550        1008 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19551         672 :            .FromJust()) {
   19552         336 :     return;
   19553             :   }
   19554             :   Local<Object>::Cast(info.This())
   19555         288 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19556         192 :       .FromJust();
   19557          96 :   info.GetReturnValue().Set(v8_num(23));
   19558             : }
   19559             : 
   19560             : 
   19561       23723 : TEST(SetterOnConstructorPrototype) {
   19562           5 :   v8::Isolate* isolate = CcTest::isolate();
   19563           5 :   v8::HandleScope scope(isolate);
   19564           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19565             :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19566           5 :                      SetterWhichSetsYOnThisTo23);
   19567          10 :   LocalContext context;
   19568          30 :   CHECK(context->Global()
   19569             :             ->Set(context.local(), v8_str("P"),
   19570             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19571             :             .FromJust());
   19572             :   CompileRun("function C1() {"
   19573             :              "  this.x = 23;"
   19574             :              "};"
   19575             :              "C1.prototype = P;"
   19576             :              "function C2() {"
   19577             :              "  this.x = 23"
   19578             :              "};"
   19579             :              "C2.prototype = { };"
   19580             :              "C2.prototype.__proto__ = P;");
   19581             : 
   19582             :   v8::Local<v8::Script> script;
   19583             :   script = v8_compile("new C1();");
   19584          55 :   for (int i = 0; i < 10; i++) {
   19585             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19586          50 :         script->Run(context.local()).ToLocalChecked());
   19587         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19588             :                      .ToLocalChecked()
   19589             :                      ->Int32Value(context.local())
   19590             :                      .FromJust());
   19591         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19592             :                      .ToLocalChecked()
   19593             :                      ->Int32Value(context.local())
   19594             :                      .FromJust());
   19595             :   }
   19596             : 
   19597             :   script = v8_compile("new C2();");
   19598          55 :   for (int i = 0; i < 10; i++) {
   19599             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19600          50 :         script->Run(context.local()).ToLocalChecked());
   19601         200 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
   19602             :                      .ToLocalChecked()
   19603             :                      ->Int32Value(context.local())
   19604             :                      .FromJust());
   19605         200 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
   19606             :                      .ToLocalChecked()
   19607             :                      ->Int32Value(context.local())
   19608             :                      .FromJust());
   19609           5 :   }
   19610           5 : }
   19611             : 
   19612             : 
   19613           0 : static void NamedPropertySetterWhichSetsYOnThisTo23(
   19614             :     Local<Name> name, Local<Value> value,
   19615             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19616           0 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
   19617           0 :           .FromJust()) {
   19618             :     Local<Object>::Cast(info.This())
   19619           0 :         ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19620           0 :         .FromJust();
   19621             :   }
   19622           0 : }
   19623             : 
   19624             : 
   19625       23724 : THREADED_TEST(InterceptorOnConstructorPrototype) {
   19626           6 :   v8::Isolate* isolate = CcTest::isolate();
   19627           6 :   v8::HandleScope scope(isolate);
   19628           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19629             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19630             :       NamedPropertyGetterWhichReturns42,
   19631           6 :       NamedPropertySetterWhichSetsYOnThisTo23));
   19632          12 :   LocalContext context;
   19633          36 :   CHECK(context->Global()
   19634             :             ->Set(context.local(), v8_str("P"),
   19635             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19636             :             .FromJust());
   19637             :   CompileRun("function C1() {"
   19638             :              "  this.x = 23;"
   19639             :              "};"
   19640             :              "C1.prototype = P;"
   19641             :              "function C2() {"
   19642             :              "  this.x = 23"
   19643             :              "};"
   19644             :              "C2.prototype = { };"
   19645             :              "C2.prototype.__proto__ = P;");
   19646             : 
   19647             :   v8::Local<v8::Script> script;
   19648             :   script = v8_compile("new C1();");
   19649          66 :   for (int i = 0; i < 10; i++) {
   19650             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19651          60 :         script->Run(context.local()).ToLocalChecked());
   19652         240 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   19653             :                      .ToLocalChecked()
   19654             :                      ->Int32Value(context.local())
   19655             :                      .FromJust());
   19656         240 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   19657             :                      .ToLocalChecked()
   19658             :                      ->Int32Value(context.local())
   19659             :                      .FromJust());
   19660             :   }
   19661             : 
   19662             :   script = v8_compile("new C2();");
   19663          66 :   for (int i = 0; i < 10; i++) {
   19664             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19665          60 :         script->Run(context.local()).ToLocalChecked());
   19666         240 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
   19667             :                      .ToLocalChecked()
   19668             :                      ->Int32Value(context.local())
   19669             :                      .FromJust());
   19670         240 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
   19671             :                      .ToLocalChecked()
   19672             :                      ->Int32Value(context.local())
   19673             :                      .FromJust());
   19674           6 :   }
   19675           6 : }
   19676             : 
   19677             : 
   19678       23723 : TEST(Regress618) {
   19679             :   const char* source = "function C1() {"
   19680             :                        "  this.x = 23;"
   19681             :                        "};"
   19682             :                        "C1.prototype = P;";
   19683             : 
   19684           5 :   LocalContext context;
   19685           5 :   v8::Isolate* isolate = context->GetIsolate();
   19686          10 :   v8::HandleScope scope(isolate);
   19687             :   v8::Local<v8::Script> script;
   19688             : 
   19689             :   // Use a simple object as prototype.
   19690           5 :   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   19691          20 :   prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
   19692          25 :   CHECK(context->Global()
   19693             :             ->Set(context.local(), v8_str("P"), prototype)
   19694             :             .FromJust());
   19695             : 
   19696             :   // This compile will add the code to the compilation cache.
   19697             :   CompileRun(source);
   19698             : 
   19699             :   script = v8_compile("new C1();");
   19700             :   // Allow enough iterations for the inobject slack tracking logic
   19701             :   // to finalize instance size and install the fast construct stub.
   19702        1285 :   for (int i = 0; i < 256; i++) {
   19703             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19704        1280 :         script->Run(context.local()).ToLocalChecked());
   19705        5120 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   19706             :                      .ToLocalChecked()
   19707             :                      ->Int32Value(context.local())
   19708             :                      .FromJust());
   19709        5120 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   19710             :                      .ToLocalChecked()
   19711             :                      ->Int32Value(context.local())
   19712             :                      .FromJust());
   19713             :   }
   19714             : 
   19715             :   // Use an API object with accessors as prototype.
   19716           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19717             :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19718           5 :                      SetterWhichSetsYOnThisTo23);
   19719          30 :   CHECK(context->Global()
   19720             :             ->Set(context.local(), v8_str("P"),
   19721             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19722             :             .FromJust());
   19723             : 
   19724             :   // This compile will get the code from the compilation cache.
   19725             :   CompileRun(source);
   19726             : 
   19727             :   script = v8_compile("new C1();");
   19728          55 :   for (int i = 0; i < 10; i++) {
   19729             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19730          50 :         script->Run(context.local()).ToLocalChecked());
   19731         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19732             :                      .ToLocalChecked()
   19733             :                      ->Int32Value(context.local())
   19734             :                      .FromJust());
   19735         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19736             :                      .ToLocalChecked()
   19737             :                      ->Int32Value(context.local())
   19738             :                      .FromJust());
   19739           5 :   }
   19740           5 : }
   19741             : 
   19742             : v8::Isolate* gc_callbacks_isolate = nullptr;
   19743             : int prologue_call_count = 0;
   19744             : int epilogue_call_count = 0;
   19745             : int prologue_call_count_second = 0;
   19746             : int epilogue_call_count_second = 0;
   19747             : int prologue_call_count_alloc = 0;
   19748             : int epilogue_call_count_alloc = 0;
   19749             : 
   19750          20 : void PrologueCallback(v8::Isolate* isolate,
   19751             :                       v8::GCType,
   19752             :                       v8::GCCallbackFlags flags) {
   19753          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19754          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19755          20 :   ++prologue_call_count;
   19756          20 : }
   19757             : 
   19758          20 : void EpilogueCallback(v8::Isolate* isolate,
   19759             :                       v8::GCType,
   19760             :                       v8::GCCallbackFlags flags) {
   19761          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19762          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19763          20 :   ++epilogue_call_count;
   19764          20 : }
   19765             : 
   19766             : 
   19767          20 : void PrologueCallbackSecond(v8::Isolate* isolate,
   19768             :                             v8::GCType,
   19769             :                             v8::GCCallbackFlags flags) {
   19770          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19771          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19772          20 :   ++prologue_call_count_second;
   19773          20 : }
   19774             : 
   19775             : 
   19776          20 : void EpilogueCallbackSecond(v8::Isolate* isolate,
   19777             :                             v8::GCType,
   19778             :                             v8::GCCallbackFlags flags) {
   19779          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19780          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19781          20 :   ++epilogue_call_count_second;
   19782          20 : }
   19783             : 
   19784          20 : void PrologueCallbackNew(v8::Isolate* isolate, v8::GCType,
   19785             :                          v8::GCCallbackFlags flags, void* data) {
   19786          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19787          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19788          20 :   ++*static_cast<int*>(data);
   19789          20 : }
   19790             : 
   19791          20 : void EpilogueCallbackNew(v8::Isolate* isolate, v8::GCType,
   19792             :                          v8::GCCallbackFlags flags, void* data) {
   19793          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19794          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19795          20 :   ++*static_cast<int*>(data);
   19796          20 : }
   19797             : 
   19798           5 : void PrologueCallbackAlloc(v8::Isolate* isolate,
   19799             :                            v8::GCType,
   19800             :                            v8::GCCallbackFlags flags) {
   19801           5 :   v8::HandleScope scope(isolate);
   19802             : 
   19803           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19804           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19805           5 :   ++prologue_call_count_alloc;
   19806             : 
   19807             :   // Simulate full heap to see if we will reenter this callback
   19808           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19809             : 
   19810           5 :   Local<Object> obj = Object::New(isolate);
   19811           5 :   CHECK(!obj.IsEmpty());
   19812             : 
   19813           5 :   CcTest::CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   19814           5 : }
   19815             : 
   19816             : 
   19817           5 : void EpilogueCallbackAlloc(v8::Isolate* isolate,
   19818             :                            v8::GCType,
   19819             :                            v8::GCCallbackFlags flags) {
   19820           5 :   v8::HandleScope scope(isolate);
   19821             : 
   19822           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19823           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19824           5 :   ++epilogue_call_count_alloc;
   19825             : 
   19826             :   // Simulate full heap to see if we will reenter this callback
   19827           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19828             : 
   19829           5 :   Local<Object> obj = Object::New(isolate);
   19830           5 :   CHECK(!obj.IsEmpty());
   19831             : 
   19832           5 :   CcTest::CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   19833           5 : }
   19834             : 
   19835             : 
   19836       23723 : TEST(GCCallbacksOld) {
   19837           5 :   LocalContext context;
   19838             : 
   19839           5 :   gc_callbacks_isolate = context->GetIsolate();
   19840             : 
   19841           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
   19842           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
   19843           5 :   CHECK_EQ(0, prologue_call_count);
   19844           5 :   CHECK_EQ(0, epilogue_call_count);
   19845           5 :   CcTest::CollectAllGarbage();
   19846           5 :   CHECK_EQ(1, prologue_call_count);
   19847           5 :   CHECK_EQ(1, epilogue_call_count);
   19848           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
   19849           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19850           5 :   CcTest::CollectAllGarbage();
   19851           5 :   CHECK_EQ(2, prologue_call_count);
   19852           5 :   CHECK_EQ(2, epilogue_call_count);
   19853           5 :   CHECK_EQ(1, prologue_call_count_second);
   19854           5 :   CHECK_EQ(1, epilogue_call_count_second);
   19855           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
   19856           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
   19857           5 :   CcTest::CollectAllGarbage();
   19858           5 :   CHECK_EQ(2, prologue_call_count);
   19859           5 :   CHECK_EQ(2, epilogue_call_count);
   19860           5 :   CHECK_EQ(2, prologue_call_count_second);
   19861           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19862           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19863           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19864           5 :   CcTest::CollectAllGarbage();
   19865           5 :   CHECK_EQ(2, prologue_call_count);
   19866           5 :   CHECK_EQ(2, epilogue_call_count);
   19867           5 :   CHECK_EQ(2, prologue_call_count_second);
   19868           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19869           5 : }
   19870             : 
   19871       23723 : TEST(GCCallbacksWithData) {
   19872           5 :   LocalContext context;
   19873             : 
   19874           5 :   gc_callbacks_isolate = context->GetIsolate();
   19875           5 :   int prologue1 = 0;
   19876           5 :   int epilogue1 = 0;
   19877           5 :   int prologue2 = 0;
   19878           5 :   int epilogue2 = 0;
   19879             : 
   19880           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue1);
   19881           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue1);
   19882           5 :   CHECK_EQ(0, prologue1);
   19883           5 :   CHECK_EQ(0, epilogue1);
   19884           5 :   CHECK_EQ(0, prologue2);
   19885           5 :   CHECK_EQ(0, epilogue2);
   19886           5 :   CcTest::CollectAllGarbage();
   19887           5 :   CHECK_EQ(1, prologue1);
   19888           5 :   CHECK_EQ(1, epilogue1);
   19889           5 :   CHECK_EQ(0, prologue2);
   19890           5 :   CHECK_EQ(0, epilogue2);
   19891           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue2);
   19892           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue2);
   19893           5 :   CcTest::CollectAllGarbage();
   19894           5 :   CHECK_EQ(2, prologue1);
   19895           5 :   CHECK_EQ(2, epilogue1);
   19896           5 :   CHECK_EQ(1, prologue2);
   19897           5 :   CHECK_EQ(1, epilogue2);
   19898             :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   19899           5 :                                                   &prologue1);
   19900             :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   19901           5 :                                                   &epilogue1);
   19902           5 :   CcTest::CollectAllGarbage();
   19903           5 :   CHECK_EQ(2, prologue1);
   19904           5 :   CHECK_EQ(2, epilogue1);
   19905           5 :   CHECK_EQ(2, prologue2);
   19906           5 :   CHECK_EQ(2, epilogue2);
   19907             :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   19908           5 :                                                   &prologue2);
   19909             :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   19910           5 :                                                   &epilogue2);
   19911           5 :   CcTest::CollectAllGarbage();
   19912           5 :   CHECK_EQ(2, prologue1);
   19913           5 :   CHECK_EQ(2, epilogue1);
   19914           5 :   CHECK_EQ(2, prologue2);
   19915           5 :   CHECK_EQ(2, epilogue2);
   19916           5 : }
   19917             : 
   19918       23723 : TEST(GCCallbacks) {
   19919           5 :   LocalContext context;
   19920           5 :   v8::Isolate* isolate = context->GetIsolate();
   19921           5 :   gc_callbacks_isolate = isolate;
   19922           5 :   isolate->AddGCPrologueCallback(PrologueCallback);
   19923           5 :   isolate->AddGCEpilogueCallback(EpilogueCallback);
   19924           5 :   CHECK_EQ(0, prologue_call_count);
   19925           5 :   CHECK_EQ(0, epilogue_call_count);
   19926           5 :   CcTest::CollectAllGarbage();
   19927           5 :   CHECK_EQ(1, prologue_call_count);
   19928           5 :   CHECK_EQ(1, epilogue_call_count);
   19929           5 :   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   19930           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19931           5 :   CcTest::CollectAllGarbage();
   19932           5 :   CHECK_EQ(2, prologue_call_count);
   19933           5 :   CHECK_EQ(2, epilogue_call_count);
   19934           5 :   CHECK_EQ(1, prologue_call_count_second);
   19935           5 :   CHECK_EQ(1, epilogue_call_count_second);
   19936           5 :   isolate->RemoveGCPrologueCallback(PrologueCallback);
   19937           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   19938           5 :   CcTest::CollectAllGarbage();
   19939           5 :   CHECK_EQ(2, prologue_call_count);
   19940           5 :   CHECK_EQ(2, epilogue_call_count);
   19941           5 :   CHECK_EQ(2, prologue_call_count_second);
   19942           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19943           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19944           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19945           5 :   CcTest::CollectAllGarbage();
   19946           5 :   CHECK_EQ(2, prologue_call_count);
   19947           5 :   CHECK_EQ(2, epilogue_call_count);
   19948           5 :   CHECK_EQ(2, prologue_call_count_second);
   19949           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19950             : 
   19951           5 :   CHECK_EQ(0, prologue_call_count_alloc);
   19952           5 :   CHECK_EQ(0, epilogue_call_count_alloc);
   19953           5 :   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   19954           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   19955           5 :   CcTest::CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   19956           5 :   CHECK_EQ(1, prologue_call_count_alloc);
   19957           5 :   CHECK_EQ(1, epilogue_call_count_alloc);
   19958           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   19959           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   19960           5 : }
   19961             : 
   19962             : 
   19963       23724 : THREADED_TEST(TwoByteStringInOneByteCons) {
   19964             :   // See Chromium issue 47824.
   19965           6 :   LocalContext context;
   19966          12 :   v8::HandleScope scope(context->GetIsolate());
   19967             : 
   19968             :   const char* init_code =
   19969             :       "var str1 = 'abelspendabel';"
   19970             :       "var str2 = str1 + str1 + str1;"
   19971             :       "str2;";
   19972             :   Local<Value> result = CompileRun(init_code);
   19973             : 
   19974           6 :   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   19975           6 :   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   19976             : 
   19977           6 :   CHECK(result->IsString());
   19978             :   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   19979             :   int length = string->length();
   19980           6 :   CHECK(string->IsOneByteRepresentation());
   19981             : 
   19982           6 :   i::Handle<i::String> flat_string = i::String::Flatten(string);
   19983             : 
   19984           6 :   CHECK(string->IsOneByteRepresentation());
   19985           6 :   CHECK(flat_string->IsOneByteRepresentation());
   19986             : 
   19987             :   // Create external resource.
   19988           6 :   uint16_t* uc16_buffer = new uint16_t[length + 1];
   19989             : 
   19990           6 :   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   19991           6 :   uc16_buffer[length] = 0;
   19992             : 
   19993           6 :   TestResource resource(uc16_buffer);
   19994             : 
   19995           6 :   flat_string->MakeExternal(&resource);
   19996             : 
   19997           6 :   CHECK(flat_string->IsTwoByteRepresentation());
   19998             : 
   19999             :   // If the cons string has been short-circuited, skip the following checks.
   20000           6 :   if (!string.is_identical_to(flat_string)) {
   20001             :     // At this point, we should have a Cons string which is flat and one-byte,
   20002             :     // with a first half that is a two-byte string (although it only contains
   20003             :     // one-byte characters). This is a valid sequence of steps, and it can
   20004             :     // happen in real pages.
   20005           6 :     CHECK(string->IsOneByteRepresentation());
   20006             :     i::ConsString* cons = i::ConsString::cast(*string);
   20007           6 :     CHECK_EQ(0, cons->second()->length());
   20008           6 :     CHECK(cons->first()->IsTwoByteRepresentation());
   20009             :   }
   20010             : 
   20011             :   // Check that some string operations work.
   20012             : 
   20013             :   // Atom RegExp.
   20014             :   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   20015          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   20016             : 
   20017             :   // Nonatom RegExp.
   20018             :   reresult = CompileRun("str2.match(/abe./g).length;");
   20019          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   20020             : 
   20021             :   reresult = CompileRun("str2.search(/bel/g);");
   20022          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   20023             : 
   20024             :   reresult = CompileRun("str2.search(/be./g);");
   20025          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   20026             : 
   20027             :   ExpectTrue("/bel/g.test(str2);");
   20028             : 
   20029             :   ExpectTrue("/be./g.test(str2);");
   20030             : 
   20031             :   reresult = CompileRun("/bel/g.exec(str2);");
   20032           6 :   CHECK(!reresult->IsNull());
   20033             : 
   20034             :   reresult = CompileRun("/be./g.exec(str2);");
   20035           6 :   CHECK(!reresult->IsNull());
   20036             : 
   20037           6 :   ExpectString("str2.substring(2, 10);", "elspenda");
   20038             : 
   20039           6 :   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   20040             : 
   20041           6 :   ExpectString("str2.charAt(2);", "e");
   20042             : 
   20043           6 :   ExpectObject("str2.indexOf('els');", indexof);
   20044             : 
   20045           6 :   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   20046             : 
   20047             :   reresult = CompileRun("str2.charCodeAt(2);");
   20048          12 :   CHECK_EQ(static_cast<int32_t>('e'),
   20049           6 :            reresult->Int32Value(context.local()).FromJust());
   20050           6 : }
   20051             : 
   20052             : 
   20053       23723 : TEST(ContainsOnlyOneByte) {
   20054           5 :   v8::V8::Initialize();
   20055           5 :   v8::Isolate* isolate = CcTest::isolate();
   20056           5 :   v8::HandleScope scope(isolate);
   20057             :   // Make a buffer long enough that it won't automatically be converted.
   20058             :   const int length = 512;
   20059             :   // Ensure word aligned assignment.
   20060             :   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   20061           5 :   std::unique_ptr<uintptr_t[]> aligned_contents(new uintptr_t[aligned_length]);
   20062             :   uint16_t* string_contents =
   20063             :       reinterpret_cast<uint16_t*>(aligned_contents.get());
   20064             :   // Set to contain only one byte.
   20065        2560 :   for (int i = 0; i < length-1; i++) {
   20066        2555 :     string_contents[i] = 0x41;
   20067             :   }
   20068           5 :   string_contents[length-1] = 0;
   20069             :   // Simple case.
   20070             :   Local<String> string =
   20071             :       String::NewExternalTwoByte(
   20072           5 :           isolate, new TestResource(string_contents, nullptr, false))
   20073           5 :           .ToLocalChecked();
   20074           5 :   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   20075             :   // Counter example.
   20076             :   string = String::NewFromTwoByte(isolate, string_contents,
   20077             :                                   v8::NewStringType::kNormal)
   20078           5 :                .ToLocalChecked();
   20079           5 :   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   20080             :   // Test left right and balanced cons strings.
   20081           5 :   Local<String> base = v8_str("a");
   20082           5 :   Local<String> left = base;
   20083           5 :   Local<String> right = base;
   20084        5005 :   for (int i = 0; i < 1000; i++) {
   20085        5000 :     left = String::Concat(base, left);
   20086        5000 :     right = String::Concat(right, base);
   20087             :   }
   20088           5 :   Local<String> balanced = String::Concat(left, base);
   20089           5 :   balanced = String::Concat(balanced, right);
   20090           5 :   Local<String> cons_strings[] = {left, balanced, right};
   20091             :   Local<String> two_byte =
   20092             :       String::NewExternalTwoByte(
   20093           5 :           isolate, new TestResource(string_contents, nullptr, false))
   20094          10 :           .ToLocalChecked();
   20095             :   USE(two_byte); USE(cons_strings);
   20096          20 :   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   20097             :     // Base assumptions.
   20098          15 :     string = cons_strings[i];
   20099          15 :     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   20100             :     // Test left and right concatentation.
   20101          15 :     string = String::Concat(two_byte, cons_strings[i]);
   20102          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   20103          15 :     string = String::Concat(cons_strings[i], two_byte);
   20104          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   20105             :   }
   20106             :   // Set bits in different positions
   20107             :   // for strings of different lengths and alignments.
   20108          35 :   for (int alignment = 0; alignment < 7; alignment++) {
   20109         280 :     for (int size = 2; alignment + size < length; size *= 2) {
   20110             :       int zero_offset = size + alignment;
   20111         280 :       string_contents[zero_offset] = 0;
   20112       18130 :       for (int i = 0; i < size; i++) {
   20113       17850 :         int shift = 8 + (i % 7);
   20114       17850 :         string_contents[alignment + i] = 1 << shift;
   20115             :         string = String::NewExternalTwoByte(
   20116             :                      isolate, new TestResource(string_contents + alignment,
   20117       17850 :                                                nullptr, false))
   20118       17850 :                      .ToLocalChecked();
   20119       17850 :         CHECK_EQ(size, string->Length());
   20120       17850 :         CHECK(!string->ContainsOnlyOneByte());
   20121       17850 :         string_contents[alignment + i] = 0x41;
   20122             :       }
   20123         280 :       string_contents[zero_offset] = 0x41;
   20124             :     }
   20125           5 :   }
   20126           5 : }
   20127             : 
   20128             : 
   20129             : // Failed access check callback that performs a GC on each invocation.
   20130          75 : void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   20131             :                                  v8::AccessType type,
   20132             :                                  Local<v8::Value> data) {
   20133          75 :   CcTest::CollectAllGarbage();
   20134             :   CcTest::isolate()->ThrowException(
   20135          75 :       v8::Exception::Error(v8_str("cross context")));
   20136          75 : }
   20137             : 
   20138             : 
   20139       23723 : TEST(GCInFailedAccessCheckCallback) {
   20140             :   // Install a failed access check callback that performs a GC on each
   20141             :   // invocation. Then force the callback to be called from va
   20142             : 
   20143           5 :   v8::V8::Initialize();
   20144           5 :   v8::Isolate* isolate = CcTest::isolate();
   20145             : 
   20146           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   20147             : 
   20148           5 :   v8::HandleScope scope(isolate);
   20149             : 
   20150             :   // Create an ObjectTemplate for global objects and install access
   20151             :   // check callbacks that will block access.
   20152             :   v8::Local<v8::ObjectTemplate> global_template =
   20153           5 :       v8::ObjectTemplate::New(isolate);
   20154           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   20155             : 
   20156             :   // Create a context and set an x property on it's global object.
   20157          10 :   LocalContext context0(nullptr, global_template);
   20158          25 :   CHECK(context0->Global()
   20159             :             ->Set(context0.local(), v8_str("x"), v8_num(42))
   20160             :             .FromJust());
   20161           5 :   v8::Local<v8::Object> global0 = context0->Global();
   20162             : 
   20163             :   // Create a context with a different security token so that the
   20164             :   // failed access check callback will be called on each access.
   20165          10 :   LocalContext context1(nullptr, global_template);
   20166          25 :   CHECK(context1->Global()
   20167             :             ->Set(context1.local(), v8_str("other"), global0)
   20168             :             .FromJust());
   20169             : 
   20170          10 :   v8::TryCatch try_catch(isolate);
   20171             : 
   20172             :   // Get property with failed access check.
   20173           5 :   CHECK(CompileRun("other.x").IsEmpty());
   20174           5 :   CHECK(try_catch.HasCaught());
   20175           5 :   try_catch.Reset();
   20176             : 
   20177             :   // Get element with failed access check.
   20178           5 :   CHECK(CompileRun("other[0]").IsEmpty());
   20179           5 :   CHECK(try_catch.HasCaught());
   20180           5 :   try_catch.Reset();
   20181             : 
   20182             :   // Set property with failed access check.
   20183           5 :   CHECK(CompileRun("other.x = new Object()").IsEmpty());
   20184           5 :   CHECK(try_catch.HasCaught());
   20185           5 :   try_catch.Reset();
   20186             : 
   20187             :   // Set element with failed access check.
   20188           5 :   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
   20189           5 :   CHECK(try_catch.HasCaught());
   20190           5 :   try_catch.Reset();
   20191             : 
   20192             :   // Get property attribute with failed access check.
   20193           5 :   CHECK(CompileRun("\'x\' in other").IsEmpty());
   20194           5 :   CHECK(try_catch.HasCaught());
   20195           5 :   try_catch.Reset();
   20196             : 
   20197             :   // Get property attribute for element with failed access check.
   20198           5 :   CHECK(CompileRun("0 in other").IsEmpty());
   20199           5 :   CHECK(try_catch.HasCaught());
   20200           5 :   try_catch.Reset();
   20201             : 
   20202             :   // Delete property.
   20203           5 :   CHECK(CompileRun("delete other.x").IsEmpty());
   20204           5 :   CHECK(try_catch.HasCaught());
   20205           5 :   try_catch.Reset();
   20206             : 
   20207             :   // Delete element.
   20208          10 :   CHECK(global0->Delete(context1.local(), 0).IsNothing());
   20209           5 :   CHECK(try_catch.HasCaught());
   20210           5 :   try_catch.Reset();
   20211             : 
   20212             :   // DefineAccessor.
   20213          20 :   CHECK(global0
   20214             :             ->SetAccessor(context1.local(), v8_str("x"), GetXValue, nullptr,
   20215             :                           v8_str("x"))
   20216             :             .IsNothing());
   20217           5 :   CHECK(try_catch.HasCaught());
   20218           5 :   try_catch.Reset();
   20219             : 
   20220             :   // Define JavaScript accessor.
   20221           5 :   CHECK(CompileRun(
   20222             :             "Object.prototype.__defineGetter__.call("
   20223             :             "    other, \'x\', function() { return 42; })").IsEmpty());
   20224           5 :   CHECK(try_catch.HasCaught());
   20225           5 :   try_catch.Reset();
   20226             : 
   20227             :   // LookupAccessor.
   20228           5 :   CHECK(CompileRun(
   20229             :             "Object.prototype.__lookupGetter__.call("
   20230             :             "    other, \'x\')").IsEmpty());
   20231           5 :   CHECK(try_catch.HasCaught());
   20232           5 :   try_catch.Reset();
   20233             : 
   20234             :   // HasOwnElement.
   20235           5 :   CHECK(CompileRun(
   20236             :             "Object.prototype.hasOwnProperty.call("
   20237             :             "other, \'0\')").IsEmpty());
   20238           5 :   CHECK(try_catch.HasCaught());
   20239           5 :   try_catch.Reset();
   20240             : 
   20241          10 :   CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
   20242           5 :   CHECK(try_catch.HasCaught());
   20243           5 :   try_catch.Reset();
   20244             : 
   20245          15 :   CHECK(
   20246             :       global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
   20247           5 :   CHECK(try_catch.HasCaught());
   20248           5 :   try_catch.Reset();
   20249             : 
   20250          15 :   CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
   20251             :             .IsNothing());
   20252           5 :   CHECK(try_catch.HasCaught());
   20253           5 :   try_catch.Reset();
   20254             : 
   20255             :   // Reset the failed access check callback so it does not influence
   20256             :   // the other tests.
   20257          10 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   20258           5 : }
   20259             : 
   20260             : 
   20261       23723 : TEST(IsolateNewDispose) {
   20262           5 :   v8::Isolate* current_isolate = CcTest::isolate();
   20263             :   v8::Isolate::CreateParams create_params;
   20264           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20265           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20266           5 :   CHECK_NOT_NULL(isolate);
   20267           5 :   CHECK(current_isolate != isolate);
   20268           5 :   CHECK(current_isolate == CcTest::isolate());
   20269             : 
   20270           5 :   isolate->SetFatalErrorHandler(StoringErrorCallback);
   20271           5 :   last_location = last_message = nullptr;
   20272           5 :   isolate->Dispose();
   20273           5 :   CHECK(!last_location);
   20274           5 :   CHECK(!last_message);
   20275           5 : }
   20276             : 
   20277             : 
   20278       23723 : UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   20279             :   v8::Isolate::CreateParams create_params;
   20280           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20281           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20282             :   {
   20283             :     v8::Isolate::Scope i_scope(isolate);
   20284          10 :     v8::HandleScope scope(isolate);
   20285           5 :     LocalContext context(isolate);
   20286             :     // Run something in this isolate.
   20287             :     ExpectTrue("true");
   20288           5 :     isolate->SetFatalErrorHandler(StoringErrorCallback);
   20289           5 :     last_location = last_message = nullptr;
   20290             :     // Still entered, should fail.
   20291           5 :     isolate->Dispose();
   20292           5 :     CHECK(last_location);
   20293           5 :     CHECK(last_message);
   20294             :   }
   20295           5 :   isolate->Dispose();
   20296           5 : }
   20297             : 
   20298             : 
   20299          40 : static void BreakArrayGuarantees(const char* script) {
   20300             :   v8::Isolate::CreateParams create_params;
   20301          40 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20302          40 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20303          40 :   isolate1->Enter();
   20304             :   v8::Persistent<v8::Context> context1;
   20305             :   {
   20306          40 :     v8::HandleScope scope(isolate1);
   20307          80 :     context1.Reset(isolate1, Context::New(isolate1));
   20308             :   }
   20309             : 
   20310             :   {
   20311          40 :     v8::HandleScope scope(isolate1);
   20312             :     v8::Local<v8::Context> context =
   20313             :         v8::Local<v8::Context>::New(isolate1, context1);
   20314             :     v8::Context::Scope context_scope(context);
   20315             :     v8::internal::Isolate* i_isolate =
   20316             :         reinterpret_cast<v8::internal::Isolate*>(isolate1);
   20317          40 :     CHECK(i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   20318             :     // Run something in new isolate.
   20319             :     CompileRun(script);
   20320          80 :     CHECK(!i_isolate->IsFastArrayConstructorPrototypeChainIntact());
   20321             :   }
   20322          40 :   isolate1->Exit();
   20323          40 :   isolate1->Dispose();
   20324          40 : }
   20325             : 
   20326             : 
   20327       23723 : TEST(VerifyArrayPrototypeGuarantees) {
   20328             :   // Break fast array hole handling by element changes.
   20329           5 :   BreakArrayGuarantees("[].__proto__[1] = 3;");
   20330           5 :   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   20331           5 :   BreakArrayGuarantees("Array.prototype.push(1);");
   20332           5 :   BreakArrayGuarantees("Array.prototype.unshift(1);");
   20333             :   // Break fast array hole handling by changing length.
   20334           5 :   BreakArrayGuarantees("Array.prototype.length = 30;");
   20335             :   // Break fast array hole handling by prototype structure changes.
   20336           5 :   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   20337             :   // By sending elements to dictionary mode.
   20338             :   BreakArrayGuarantees(
   20339             :       "Object.defineProperty(Array.prototype, 0, {"
   20340           5 :       "  get: function() { return 3; }});");
   20341             :   BreakArrayGuarantees(
   20342             :       "Object.defineProperty(Object.prototype, 0, {"
   20343           5 :       "  get: function() { return 3; }});");
   20344           5 : }
   20345             : 
   20346             : 
   20347       23723 : TEST(RunTwoIsolatesOnSingleThread) {
   20348             :   // Run isolate 1.
   20349             :   v8::Isolate::CreateParams create_params;
   20350           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20351           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20352           5 :   isolate1->Enter();
   20353             :   v8::Persistent<v8::Context> context1;
   20354             :   {
   20355           5 :     v8::HandleScope scope(isolate1);
   20356          10 :     context1.Reset(isolate1, Context::New(isolate1));
   20357             :   }
   20358             : 
   20359             :   {
   20360           5 :     v8::HandleScope scope(isolate1);
   20361             :     v8::Local<v8::Context> context =
   20362             :         v8::Local<v8::Context>::New(isolate1, context1);
   20363             :     v8::Context::Scope context_scope(context);
   20364             :     // Run something in new isolate.
   20365             :     CompileRun("var foo = 'isolate 1';");
   20366          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20367             :   }
   20368             : 
   20369             :   // Run isolate 2.
   20370           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   20371             :   v8::Persistent<v8::Context> context2;
   20372             : 
   20373             :   {
   20374             :     v8::Isolate::Scope iscope(isolate2);
   20375          10 :     v8::HandleScope scope(isolate2);
   20376          10 :     context2.Reset(isolate2, Context::New(isolate2));
   20377             :     v8::Local<v8::Context> context =
   20378             :         v8::Local<v8::Context>::New(isolate2, context2);
   20379             :     v8::Context::Scope context_scope(context);
   20380             : 
   20381             :     // Run something in new isolate.
   20382             :     CompileRun("var foo = 'isolate 2';");
   20383           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20384             :   }
   20385             : 
   20386             :   {
   20387           5 :     v8::HandleScope scope(isolate1);
   20388             :     v8::Local<v8::Context> context =
   20389             :         v8::Local<v8::Context>::New(isolate1, context1);
   20390             :     v8::Context::Scope context_scope(context);
   20391             :     // Now again in isolate 1
   20392          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20393             :   }
   20394             : 
   20395           5 :   isolate1->Exit();
   20396             : 
   20397             :   // Run some stuff in default isolate.
   20398             :   v8::Persistent<v8::Context> context_default;
   20399             :   {
   20400           5 :     v8::Isolate* isolate = CcTest::isolate();
   20401             :     v8::Isolate::Scope iscope(isolate);
   20402          10 :     v8::HandleScope scope(isolate);
   20403          10 :     context_default.Reset(isolate, Context::New(isolate));
   20404             :   }
   20405             : 
   20406             :   {
   20407           5 :     v8::HandleScope scope(CcTest::isolate());
   20408             :     v8::Local<v8::Context> context =
   20409           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20410             :     v8::Context::Scope context_scope(context);
   20411             :     // Variables in other isolates should be not available, verify there
   20412             :     // is an exception.
   20413             :     ExpectTrue("function f() {"
   20414             :                "  try {"
   20415             :                "    foo;"
   20416             :                "    return false;"
   20417             :                "  } catch(e) {"
   20418             :                "    return true;"
   20419             :                "  }"
   20420             :                "};"
   20421             :                "var isDefaultIsolate = true;"
   20422           5 :                "f()");
   20423             :   }
   20424             : 
   20425           5 :   isolate1->Enter();
   20426             : 
   20427             :   {
   20428             :     v8::Isolate::Scope iscope(isolate2);
   20429          10 :     v8::HandleScope scope(isolate2);
   20430             :     v8::Local<v8::Context> context =
   20431             :         v8::Local<v8::Context>::New(isolate2, context2);
   20432             :     v8::Context::Scope context_scope(context);
   20433           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20434             :   }
   20435             : 
   20436             :   {
   20437           5 :     v8::HandleScope scope(v8::Isolate::GetCurrent());
   20438             :     v8::Local<v8::Context> context =
   20439           5 :         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   20440             :     v8::Context::Scope context_scope(context);
   20441          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20442             :   }
   20443             : 
   20444             :   {
   20445             :     v8::Isolate::Scope iscope(isolate2);
   20446             :     context2.Reset();
   20447             :   }
   20448             : 
   20449             :   context1.Reset();
   20450           5 :   isolate1->Exit();
   20451             : 
   20452           5 :   isolate2->SetFatalErrorHandler(StoringErrorCallback);
   20453           5 :   last_location = last_message = nullptr;
   20454             : 
   20455           5 :   isolate1->Dispose();
   20456           5 :   CHECK(!last_location);
   20457           5 :   CHECK(!last_message);
   20458             : 
   20459           5 :   isolate2->Dispose();
   20460           5 :   CHECK(!last_location);
   20461           5 :   CHECK(!last_message);
   20462             : 
   20463             :   // Check that default isolate still runs.
   20464             :   {
   20465           5 :     v8::HandleScope scope(CcTest::isolate());
   20466             :     v8::Local<v8::Context> context =
   20467           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20468             :     v8::Context::Scope context_scope(context);
   20469           5 :     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   20470             :   }
   20471           5 : }
   20472             : 
   20473             : 
   20474          20 : static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   20475             :   v8::Isolate::Scope isolate_scope(isolate);
   20476          40 :   v8::HandleScope scope(isolate);
   20477          20 :   LocalContext context(isolate);
   20478             :   i::ScopedVector<char> code(1024);
   20479             :   i::SNPrintF(code, "function fib(n) {"
   20480             :                     "  if (n <= 2) return 1;"
   20481             :                     "  return fib(n-1) + fib(n-2);"
   20482             :                     "}"
   20483          20 :                     "fib(%d)", limit);
   20484             :   Local<Value> value = CompileRun(code.start());
   20485          20 :   CHECK(value->IsNumber());
   20486          60 :   return static_cast<int>(value->NumberValue(context.local()).FromJust());
   20487             : }
   20488             : 
   20489           5 : class IsolateThread : public v8::base::Thread {
   20490             :  public:
   20491             :   explicit IsolateThread(int fib_limit)
   20492          10 :       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   20493             : 
   20494          10 :   void Run() {
   20495             :     v8::Isolate::CreateParams create_params;
   20496          10 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20497          10 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20498          10 :     result_ = CalcFibonacci(isolate, fib_limit_);
   20499          10 :     isolate->Dispose();
   20500          10 :   }
   20501             : 
   20502             :   int result() { return result_; }
   20503             : 
   20504             :  private:
   20505             :   int fib_limit_;
   20506             :   int result_;
   20507             : };
   20508             : 
   20509             : 
   20510       23723 : TEST(MultipleIsolatesOnIndividualThreads) {
   20511             :   IsolateThread thread1(21);
   20512             :   IsolateThread thread2(12);
   20513             : 
   20514             :   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   20515           5 :   thread1.Start();
   20516           5 :   thread2.Start();
   20517             : 
   20518           5 :   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   20519           5 :   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   20520             : 
   20521           5 :   thread1.Join();
   20522           5 :   thread2.Join();
   20523             : 
   20524             :   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   20525             :   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   20526           5 :   CHECK_EQ(result1, 10946);
   20527           5 :   CHECK_EQ(result2, 144);
   20528           5 :   CHECK_EQ(result1, thread1.result());
   20529           5 :   CHECK_EQ(result2, thread2.result());
   20530           5 : }
   20531             : 
   20532             : 
   20533       23723 : TEST(IsolateDifferentContexts) {
   20534             :   v8::Isolate::CreateParams create_params;
   20535           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20536           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20537             :   Local<v8::Context> context;
   20538             :   {
   20539             :     v8::Isolate::Scope isolate_scope(isolate);
   20540          10 :     v8::HandleScope handle_scope(isolate);
   20541           5 :     context = v8::Context::New(isolate);
   20542             :     v8::Context::Scope context_scope(context);
   20543             :     Local<Value> v = CompileRun("2");
   20544           5 :     CHECK(v->IsNumber());
   20545          10 :     CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
   20546             :   }
   20547             :   {
   20548             :     v8::Isolate::Scope isolate_scope(isolate);
   20549          10 :     v8::HandleScope handle_scope(isolate);
   20550           5 :     context = v8::Context::New(isolate);
   20551             :     v8::Context::Scope context_scope(context);
   20552             :     Local<Value> v = CompileRun("22");
   20553           5 :     CHECK(v->IsNumber());
   20554          10 :     CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
   20555             :   }
   20556           5 :   isolate->Dispose();
   20557           5 : }
   20558             : 
   20559          25 : class InitDefaultIsolateThread : public v8::base::Thread {
   20560             :  public:
   20561             :   enum TestCase {
   20562             :     SetResourceConstraints,
   20563             :     SetFatalHandler,
   20564             :     SetCounterFunction,
   20565             :     SetCreateHistogramFunction,
   20566             :     SetAddHistogramSampleFunction
   20567             :   };
   20568             : 
   20569             :   explicit InitDefaultIsolateThread(TestCase testCase)
   20570             :       : Thread(Options("InitDefaultIsolateThread")),
   20571             :         testCase_(testCase),
   20572          25 :         result_(false) {}
   20573             : 
   20574          25 :   void Run() {
   20575             :     v8::Isolate::CreateParams create_params;
   20576          25 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20577          25 :     switch (testCase_) {
   20578             :       case SetResourceConstraints: {
   20579             :         create_params.constraints.set_max_semi_space_size_in_kb(1024);
   20580             :         create_params.constraints.set_max_old_space_size(6);
   20581             :         break;
   20582             :       }
   20583             :       default:
   20584             :         break;
   20585             :     }
   20586          25 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20587          25 :     isolate->Enter();
   20588          25 :     switch (testCase_) {
   20589             :       case SetResourceConstraints:
   20590             :         // Already handled in pre-Isolate-creation block.
   20591             :         break;
   20592             : 
   20593             :       case SetFatalHandler:
   20594           5 :         isolate->SetFatalErrorHandler(nullptr);
   20595           5 :         break;
   20596             : 
   20597             :       case SetCounterFunction:
   20598           5 :         CcTest::isolate()->SetCounterFunction(nullptr);
   20599           5 :         break;
   20600             : 
   20601             :       case SetCreateHistogramFunction:
   20602           5 :         CcTest::isolate()->SetCreateHistogramFunction(nullptr);
   20603           5 :         break;
   20604             : 
   20605             :       case SetAddHistogramSampleFunction:
   20606           5 :         CcTest::isolate()->SetAddHistogramSampleFunction(nullptr);
   20607           5 :         break;
   20608             :     }
   20609          25 :     isolate->Exit();
   20610          25 :     isolate->Dispose();
   20611          25 :     result_ = true;
   20612          25 :   }
   20613             : 
   20614             :   bool result() { return result_; }
   20615             : 
   20616             :  private:
   20617             :   TestCase testCase_;
   20618             :   bool result_;
   20619             : };
   20620             : 
   20621             : 
   20622          25 : static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   20623             :   InitDefaultIsolateThread thread(testCase);
   20624          25 :   thread.Start();
   20625          25 :   thread.Join();
   20626          25 :   CHECK(thread.result());
   20627          25 : }
   20628             : 
   20629             : 
   20630       23723 : TEST(InitializeDefaultIsolateOnSecondaryThread1) {
   20631           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
   20632           5 : }
   20633             : 
   20634             : 
   20635       23723 : TEST(InitializeDefaultIsolateOnSecondaryThread2) {
   20636           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   20637           5 : }
   20638             : 
   20639             : 
   20640       23723 : TEST(InitializeDefaultIsolateOnSecondaryThread3) {
   20641           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   20642           5 : }
   20643             : 
   20644             : 
   20645       23723 : TEST(InitializeDefaultIsolateOnSecondaryThread4) {
   20646           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   20647           5 : }
   20648             : 
   20649             : 
   20650       23723 : TEST(InitializeDefaultIsolateOnSecondaryThread5) {
   20651           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   20652           5 : }
   20653             : 
   20654             : 
   20655       23723 : TEST(StringCheckMultipleContexts) {
   20656             :   const char* code =
   20657             :       "(function() { return \"a\".charAt(0); })()";
   20658             : 
   20659             :   {
   20660             :     // Run the code twice in the first context to initialize the call IC.
   20661           5 :     LocalContext context1;
   20662          10 :     v8::HandleScope scope(context1->GetIsolate());
   20663           5 :     ExpectString(code, "a");
   20664          10 :     ExpectString(code, "a");
   20665             :   }
   20666             : 
   20667             :   {
   20668             :     // Change the String.prototype in the second context and check
   20669             :     // that the right function gets called.
   20670           5 :     LocalContext context2;
   20671          10 :     v8::HandleScope scope(context2->GetIsolate());
   20672             :     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   20673          10 :     ExpectString(code, "not a");
   20674             :   }
   20675           5 : }
   20676             : 
   20677             : 
   20678       23723 : TEST(NumberCheckMultipleContexts) {
   20679             :   const char* code =
   20680             :       "(function() { return (42).toString(); })()";
   20681             : 
   20682             :   {
   20683             :     // Run the code twice in the first context to initialize the call IC.
   20684           5 :     LocalContext context1;
   20685          10 :     v8::HandleScope scope(context1->GetIsolate());
   20686           5 :     ExpectString(code, "42");
   20687          10 :     ExpectString(code, "42");
   20688             :   }
   20689             : 
   20690             :   {
   20691             :     // Change the Number.prototype in the second context and check
   20692             :     // that the right function gets called.
   20693           5 :     LocalContext context2;
   20694          10 :     v8::HandleScope scope(context2->GetIsolate());
   20695             :     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   20696          10 :     ExpectString(code, "not 42");
   20697             :   }
   20698           5 : }
   20699             : 
   20700             : 
   20701       23723 : TEST(BooleanCheckMultipleContexts) {
   20702             :   const char* code =
   20703             :       "(function() { return true.toString(); })()";
   20704             : 
   20705             :   {
   20706             :     // Run the code twice in the first context to initialize the call IC.
   20707           5 :     LocalContext context1;
   20708          10 :     v8::HandleScope scope(context1->GetIsolate());
   20709           5 :     ExpectString(code, "true");
   20710          10 :     ExpectString(code, "true");
   20711             :   }
   20712             : 
   20713             :   {
   20714             :     // Change the Boolean.prototype in the second context and check
   20715             :     // that the right function gets called.
   20716           5 :     LocalContext context2;
   20717          10 :     v8::HandleScope scope(context2->GetIsolate());
   20718             :     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   20719          10 :     ExpectString(code, "");
   20720             :   }
   20721           5 : }
   20722             : 
   20723             : 
   20724       23723 : TEST(DontDeleteCellLoadIC) {
   20725             :   const char* function_code =
   20726             :       "function readCell() { while (true) { return cell; } }";
   20727             : 
   20728             :   {
   20729             :     // Run the code twice in the first context to initialize the load
   20730             :     // IC for a don't delete cell.
   20731           5 :     LocalContext context1;
   20732          10 :     v8::HandleScope scope(context1->GetIsolate());
   20733             :     CompileRun("var cell = \"first\";");
   20734           5 :     ExpectBoolean("delete cell", false);
   20735             :     CompileRun(function_code);
   20736           5 :     ExpectString("readCell()", "first");
   20737          10 :     ExpectString("readCell()", "first");
   20738             :   }
   20739             : 
   20740             :   {
   20741             :     // Use a deletable cell in the second context.
   20742           5 :     LocalContext context2;
   20743          10 :     v8::HandleScope scope(context2->GetIsolate());
   20744             :     CompileRun("cell = \"second\";");
   20745             :     CompileRun(function_code);
   20746           5 :     ExpectString("readCell()", "second");
   20747           5 :     ExpectBoolean("delete cell", true);
   20748             :     ExpectString("(function() {"
   20749             :                  "  try {"
   20750             :                  "    return readCell();"
   20751             :                  "  } catch(e) {"
   20752             :                  "    return e.toString();"
   20753             :                  "  }"
   20754             :                  "})()",
   20755           5 :                  "ReferenceError: cell is not defined");
   20756             :     CompileRun("cell = \"new_second\";");
   20757           5 :     CcTest::CollectAllGarbage();
   20758           5 :     ExpectString("readCell()", "new_second");
   20759          10 :     ExpectString("readCell()", "new_second");
   20760             :   }
   20761           5 : }
   20762             : 
   20763             : 
   20764          10 : class Visitor42 : public v8::PersistentHandleVisitor {
   20765             :  public:
   20766             :   explicit Visitor42(v8::Persistent<v8::Object>* object)
   20767          10 :       : counter_(0), object_(object) { }
   20768             : 
   20769          10 :   virtual void VisitPersistentHandle(Persistent<Value>* value,
   20770             :                                      uint16_t class_id) {
   20771          10 :     if (class_id != 42) return;
   20772          10 :     CHECK_EQ(42, value->WrapperClassId());
   20773          10 :     v8::Isolate* isolate = CcTest::isolate();
   20774          10 :     v8::HandleScope handle_scope(isolate);
   20775             :     v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   20776          10 :     v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
   20777          10 :     CHECK(handle->IsObject());
   20778          20 :     CHECK(Local<Object>::Cast(handle)
   20779             :               ->Equals(isolate->GetCurrentContext(), object)
   20780             :               .FromJust());
   20781          10 :     ++counter_;
   20782             :   }
   20783             : 
   20784             :   int counter_;
   20785             :   v8::Persistent<v8::Object>* object_;
   20786             : };
   20787             : 
   20788             : 
   20789       23723 : TEST(PersistentHandleVisitor) {
   20790           5 :   LocalContext context;
   20791           5 :   v8::Isolate* isolate = context->GetIsolate();
   20792          10 :   v8::HandleScope scope(isolate);
   20793           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20794           5 :   CHECK_EQ(0, object.WrapperClassId());
   20795             :   object.SetWrapperClassId(42);
   20796           5 :   CHECK_EQ(42, object.WrapperClassId());
   20797             : 
   20798             :   Visitor42 visitor(&object);
   20799           5 :   isolate->VisitHandlesWithClassIds(&visitor);
   20800           5 :   CHECK_EQ(1, visitor.counter_);
   20801             : 
   20802           5 :   object.Reset();
   20803           5 : }
   20804             : 
   20805             : 
   20806       23723 : TEST(WrapperClassId) {
   20807           5 :   LocalContext context;
   20808           5 :   v8::Isolate* isolate = context->GetIsolate();
   20809          10 :   v8::HandleScope scope(isolate);
   20810           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20811           5 :   CHECK_EQ(0, object.WrapperClassId());
   20812             :   object.SetWrapperClassId(65535);
   20813           5 :   CHECK_EQ(65535, object.WrapperClassId());
   20814           5 :   object.Reset();
   20815           5 : }
   20816             : 
   20817             : 
   20818       23723 : TEST(PersistentHandleInNewSpaceVisitor) {
   20819           5 :   LocalContext context;
   20820           5 :   v8::Isolate* isolate = context->GetIsolate();
   20821          10 :   v8::HandleScope scope(isolate);
   20822           5 :   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
   20823           5 :   CHECK_EQ(0, object1.WrapperClassId());
   20824             :   object1.SetWrapperClassId(42);
   20825           5 :   CHECK_EQ(42, object1.WrapperClassId());
   20826             : 
   20827           5 :   CcTest::CollectAllGarbage();
   20828           5 :   CcTest::CollectAllGarbage();
   20829             : 
   20830           5 :   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
   20831           5 :   CHECK_EQ(0, object2.WrapperClassId());
   20832             :   object2.SetWrapperClassId(42);
   20833           5 :   CHECK_EQ(42, object2.WrapperClassId());
   20834             : 
   20835             :   Visitor42 visitor(&object2);
   20836           5 :   isolate->VisitHandlesForPartialDependence(&visitor);
   20837           5 :   CHECK_EQ(1, visitor.counter_);
   20838             : 
   20839             :   object1.Reset();
   20840           5 :   object2.Reset();
   20841           5 : }
   20842             : 
   20843             : 
   20844       23723 : TEST(RegExp) {
   20845           5 :   LocalContext context;
   20846          10 :   v8::HandleScope scope(context->GetIsolate());
   20847             : 
   20848             :   v8::Local<v8::RegExp> re =
   20849           5 :       v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
   20850           5 :           .ToLocalChecked();
   20851           5 :   CHECK(re->IsRegExp());
   20852          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
   20853           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20854             : 
   20855             :   re = v8::RegExp::New(context.local(), v8_str("bar"),
   20856             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20857           5 :                                                       v8::RegExp::kGlobal))
   20858           5 :            .ToLocalChecked();
   20859           5 :   CHECK(re->IsRegExp());
   20860          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
   20861           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   20862             :            static_cast<int>(re->GetFlags()));
   20863             : 
   20864             :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20865             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20866           5 :                                                       v8::RegExp::kMultiline))
   20867           5 :            .ToLocalChecked();
   20868           5 :   CHECK(re->IsRegExp());
   20869          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20870           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20871             :            static_cast<int>(re->GetFlags()));
   20872             : 
   20873             :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20874             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
   20875           5 :                                                       v8::RegExp::kSticky))
   20876           5 :            .ToLocalChecked();
   20877           5 :   CHECK(re->IsRegExp());
   20878          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20879           5 :   CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
   20880             :            static_cast<int>(re->GetFlags()));
   20881             : 
   20882             :   re = CompileRun("/quux/").As<v8::RegExp>();
   20883           5 :   CHECK(re->IsRegExp());
   20884          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20885           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20886             : 
   20887             :   re = CompileRun("/quux/gm").As<v8::RegExp>();
   20888           5 :   CHECK(re->IsRegExp());
   20889          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20890           5 :   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   20891             :            static_cast<int>(re->GetFlags()));
   20892             : 
   20893             :   // Override the RegExp constructor and check the API constructor
   20894             :   // still works.
   20895             :   CompileRun("RegExp = function() {}");
   20896             : 
   20897           5 :   re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
   20898           5 :            .ToLocalChecked();
   20899           5 :   CHECK(re->IsRegExp());
   20900          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
   20901           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20902             : 
   20903             :   re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
   20904             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20905           5 :                                                       v8::RegExp::kMultiline))
   20906           5 :            .ToLocalChecked();
   20907           5 :   CHECK(re->IsRegExp());
   20908          20 :   CHECK(
   20909             :       re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
   20910           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20911             :            static_cast<int>(re->GetFlags()));
   20912             : 
   20913          25 :   CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
   20914             :   ExpectTrue("re.test('FoobarbaZ')");
   20915             : 
   20916             :   // RegExps are objects on which you can set properties.
   20917             :   re->Set(context.local(), v8_str("property"),
   20918          20 :           v8::Integer::New(context->GetIsolate(), 32))
   20919          10 :       .FromJust();
   20920             :   v8::Local<v8::Value> value(CompileRun("re.property"));
   20921          10 :   CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
   20922             : 
   20923          10 :   v8::TryCatch try_catch(context->GetIsolate());
   20924          10 :   CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
   20925             :             .IsEmpty());
   20926           5 :   CHECK(try_catch.HasCaught());
   20927          25 :   CHECK(context->Global()
   20928             :             ->Set(context.local(), v8_str("ex"), try_catch.Exception())
   20929             :             .FromJust());
   20930           5 :   ExpectTrue("ex instanceof SyntaxError");
   20931           5 : }
   20932             : 
   20933             : 
   20934       23724 : THREADED_TEST(Equals) {
   20935           6 :   LocalContext localContext;
   20936          12 :   v8::HandleScope handleScope(localContext->GetIsolate());
   20937             : 
   20938           6 :   v8::Local<v8::Object> globalProxy = localContext->Global();
   20939           6 :   v8::Local<Value> global = globalProxy->GetPrototype();
   20940             : 
   20941           6 :   CHECK(global->StrictEquals(global));
   20942           6 :   CHECK(!global->StrictEquals(globalProxy));
   20943           6 :   CHECK(!globalProxy->StrictEquals(global));
   20944           6 :   CHECK(globalProxy->StrictEquals(globalProxy));
   20945             : 
   20946          12 :   CHECK(global->Equals(localContext.local(), global).FromJust());
   20947          12 :   CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
   20948          12 :   CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
   20949          18 :   CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
   20950           6 : }
   20951             : 
   20952             : 
   20953           5 : static void Getter(v8::Local<v8::Name> property,
   20954             :                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   20955           5 :   info.GetReturnValue().Set(v8_str("42!"));
   20956           5 : }
   20957             : 
   20958             : 
   20959           5 : static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   20960           5 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
   20961             :   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
   20962          15 :               v8_str("universalAnswer"))
   20963          10 :       .FromJust();
   20964             :   info.GetReturnValue().Set(result);
   20965           5 : }
   20966             : 
   20967             : 
   20968       23723 : TEST(NamedEnumeratorAndForIn) {
   20969           5 :   LocalContext context;
   20970           5 :   v8::Isolate* isolate = context->GetIsolate();
   20971          10 :   v8::HandleScope handle_scope(isolate);
   20972           5 :   v8::Context::Scope context_scope(context.local());
   20973             : 
   20974           5 :   v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   20975             :   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20976           5 :       Getter, nullptr, nullptr, nullptr, Enumerator));
   20977          30 :   CHECK(context->Global()
   20978             :             ->Set(context.local(), v8_str("o"),
   20979             :                   tmpl->NewInstance(context.local()).ToLocalChecked())
   20980             :             .FromJust());
   20981             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   20982             :       CompileRun("var result = []; for (var k in o) result.push(k); result"));
   20983           5 :   CHECK_EQ(1u, result->Length());
   20984          20 :   CHECK(v8_str("universalAnswer")
   20985             :             ->Equals(context.local(),
   20986             :                      result->Get(context.local(), 0).ToLocalChecked())
   20987           5 :             .FromJust());
   20988           5 : }
   20989             : 
   20990             : 
   20991       23723 : TEST(DefinePropertyPostDetach) {
   20992           5 :   LocalContext context;
   20993          10 :   v8::HandleScope scope(context->GetIsolate());
   20994           5 :   v8::Local<v8::Object> proxy = context->Global();
   20995             :   v8::Local<v8::Function> define_property =
   20996             :       CompileRun(
   20997             :           "(function() {"
   20998             :           "  Object.defineProperty("
   20999             :           "    this,"
   21000             :           "    1,"
   21001             :           "    { configurable: true, enumerable: true, value: 3 });"
   21002             :           "})")
   21003             :           .As<Function>();
   21004           5 :   context->DetachGlobal();
   21005          15 :   CHECK(define_property->Call(context.local(), proxy, 0, nullptr).IsEmpty());
   21006           5 : }
   21007             : 
   21008             : 
   21009          36 : static void InstallContextId(v8::Local<Context> context, int id) {
   21010             :   Context::Scope scope(context);
   21011         144 :   CHECK(CompileRun("Object.prototype")
   21012             :             .As<Object>()
   21013             :             ->Set(context, v8_str("context_id"),
   21014             :                   v8::Integer::New(context->GetIsolate(), id))
   21015             :             .FromJust());
   21016          36 : }
   21017             : 
   21018             : 
   21019         126 : static void CheckContextId(v8::Local<Object> object, int expected) {
   21020         126 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   21021         504 :   CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
   21022             :                          .ToLocalChecked()
   21023             :                          ->Int32Value(context)
   21024             :                          .FromJust());
   21025         126 : }
   21026             : 
   21027             : 
   21028       23724 : THREADED_TEST(CreationContext) {
   21029           6 :   v8::Isolate* isolate = CcTest::isolate();
   21030           6 :   HandleScope handle_scope(isolate);
   21031           6 :   Local<Context> context1 = Context::New(isolate);
   21032           6 :   InstallContextId(context1, 1);
   21033           6 :   Local<Context> context2 = Context::New(isolate);
   21034           6 :   InstallContextId(context2, 2);
   21035           6 :   Local<Context> context3 = Context::New(isolate);
   21036           6 :   InstallContextId(context3, 3);
   21037             : 
   21038           6 :   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   21039             : 
   21040             :   Local<Object> object1;
   21041             :   Local<Function> func1;
   21042             :   {
   21043             :     Context::Scope scope(context1);
   21044           6 :     object1 = Object::New(isolate);
   21045           6 :     func1 = tmpl->GetFunction(context1).ToLocalChecked();
   21046             :   }
   21047             : 
   21048             :   Local<Object> object2;
   21049             :   Local<Function> func2;
   21050             :   {
   21051             :     Context::Scope scope(context2);
   21052           6 :     object2 = Object::New(isolate);
   21053           6 :     func2 = tmpl->GetFunction(context2).ToLocalChecked();
   21054             :   }
   21055             : 
   21056             :   Local<Object> instance1;
   21057             :   Local<Object> instance2;
   21058             : 
   21059             :   {
   21060             :     Context::Scope scope(context3);
   21061             :     instance1 = func1->NewInstance(context3).ToLocalChecked();
   21062             :     instance2 = func2->NewInstance(context3).ToLocalChecked();
   21063             :   }
   21064             : 
   21065             :   {
   21066           6 :     Local<Context> other_context = Context::New(isolate);
   21067             :     Context::Scope scope(other_context);
   21068          12 :     CHECK(object1->CreationContext() == context1);
   21069           6 :     CheckContextId(object1, 1);
   21070          12 :     CHECK(func1->CreationContext() == context1);
   21071           6 :     CheckContextId(func1, 1);
   21072          12 :     CHECK(instance1->CreationContext() == context1);
   21073           6 :     CheckContextId(instance1, 1);
   21074          12 :     CHECK(object2->CreationContext() == context2);
   21075           6 :     CheckContextId(object2, 2);
   21076          12 :     CHECK(func2->CreationContext() == context2);
   21077           6 :     CheckContextId(func2, 2);
   21078          12 :     CHECK(instance2->CreationContext() == context2);
   21079           6 :     CheckContextId(instance2, 2);
   21080             :   }
   21081             : 
   21082             :   {
   21083             :     Context::Scope scope(context1);
   21084          12 :     CHECK(object1->CreationContext() == context1);
   21085           6 :     CheckContextId(object1, 1);
   21086          12 :     CHECK(func1->CreationContext() == context1);
   21087           6 :     CheckContextId(func1, 1);
   21088          12 :     CHECK(instance1->CreationContext() == context1);
   21089           6 :     CheckContextId(instance1, 1);
   21090          12 :     CHECK(object2->CreationContext() == context2);
   21091           6 :     CheckContextId(object2, 2);
   21092          12 :     CHECK(func2->CreationContext() == context2);
   21093           6 :     CheckContextId(func2, 2);
   21094          12 :     CHECK(instance2->CreationContext() == context2);
   21095           6 :     CheckContextId(instance2, 2);
   21096             :   }
   21097             : 
   21098             :   {
   21099             :     Context::Scope scope(context2);
   21100          12 :     CHECK(object1->CreationContext() == context1);
   21101           6 :     CheckContextId(object1, 1);
   21102          12 :     CHECK(func1->CreationContext() == context1);
   21103           6 :     CheckContextId(func1, 1);
   21104          12 :     CHECK(instance1->CreationContext() == context1);
   21105           6 :     CheckContextId(instance1, 1);
   21106          12 :     CHECK(object2->CreationContext() == context2);
   21107           6 :     CheckContextId(object2, 2);
   21108          12 :     CHECK(func2->CreationContext() == context2);
   21109           6 :     CheckContextId(func2, 2);
   21110          12 :     CHECK(instance2->CreationContext() == context2);
   21111           6 :     CheckContextId(instance2, 2);
   21112           6 :   }
   21113           6 : }
   21114             : 
   21115             : 
   21116       23724 : THREADED_TEST(CreationContextOfJsFunction) {
   21117           6 :   HandleScope handle_scope(CcTest::isolate());
   21118           6 :   Local<Context> context = Context::New(CcTest::isolate());
   21119           6 :   InstallContextId(context, 1);
   21120             : 
   21121             :   Local<Object> function;
   21122             :   {
   21123             :     Context::Scope scope(context);
   21124             :     function = CompileRun("function foo() {}; foo").As<Object>();
   21125             :   }
   21126             : 
   21127           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   21128             :   Context::Scope scope(other_context);
   21129          12 :   CHECK(function->CreationContext() == context);
   21130          12 :   CheckContextId(function, 1);
   21131           6 : }
   21132             : 
   21133             : 
   21134       23724 : THREADED_TEST(CreationContextOfJsBoundFunction) {
   21135           6 :   HandleScope handle_scope(CcTest::isolate());
   21136           6 :   Local<Context> context1 = Context::New(CcTest::isolate());
   21137           6 :   InstallContextId(context1, 1);
   21138           6 :   Local<Context> context2 = Context::New(CcTest::isolate());
   21139           6 :   InstallContextId(context2, 2);
   21140             : 
   21141             :   Local<Function> target_function;
   21142             :   {
   21143             :     Context::Scope scope(context1);
   21144             :     target_function = CompileRun("function foo() {}; foo").As<Function>();
   21145             :   }
   21146             : 
   21147             :   Local<Function> bound_function1, bound_function2;
   21148             :   {
   21149             :     Context::Scope scope(context2);
   21150          24 :     CHECK(context2->Global()
   21151             :               ->Set(context2, v8_str("foo"), target_function)
   21152             :               .FromJust());
   21153             :     bound_function1 = CompileRun("foo.bind(1)").As<Function>();
   21154             :     bound_function2 =
   21155             :         CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
   21156             :   }
   21157             : 
   21158           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   21159             :   Context::Scope scope(other_context);
   21160          12 :   CHECK(bound_function1->CreationContext() == context1);
   21161           6 :   CheckContextId(bound_function1, 1);
   21162          12 :   CHECK(bound_function2->CreationContext() == context1);
   21163          12 :   CheckContextId(bound_function2, 1);
   21164           6 : }
   21165             : 
   21166             : 
   21167          20 : void HasOwnPropertyIndexedPropertyGetter(
   21168             :     uint32_t index,
   21169             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21170          20 :   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   21171          20 : }
   21172             : 
   21173             : 
   21174          10 : void HasOwnPropertyNamedPropertyGetter(
   21175             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   21176          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21177          20 :           .FromJust()) {
   21178           5 :     info.GetReturnValue().Set(v8_str("yes"));
   21179             :   }
   21180          10 : }
   21181             : 
   21182             : 
   21183          50 : void HasOwnPropertyIndexedPropertyQuery(
   21184             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   21185          50 :   if (index == 42) info.GetReturnValue().Set(1);
   21186          50 : }
   21187             : 
   21188             : 
   21189          10 : void HasOwnPropertyNamedPropertyQuery(
   21190             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   21191          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21192          20 :           .FromJust()) {
   21193             :     info.GetReturnValue().Set(1);
   21194             :   }
   21195          10 : }
   21196             : 
   21197             : 
   21198          10 : void HasOwnPropertyNamedPropertyQuery2(
   21199             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   21200          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
   21201          20 :           .FromJust()) {
   21202             :     info.GetReturnValue().Set(1);
   21203             :   }
   21204          10 : }
   21205             : 
   21206           0 : void HasOwnPropertyAccessorGetter(
   21207             :     Local<String> property,
   21208             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21209           0 :   info.GetReturnValue().Set(v8_str("yes"));
   21210           0 : }
   21211             : 
   21212           5 : void HasOwnPropertyAccessorNameGetter(
   21213             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   21214           5 :   info.GetReturnValue().Set(v8_str("yes"));
   21215           5 : }
   21216             : 
   21217       23723 : TEST(HasOwnProperty) {
   21218           5 :   LocalContext env;
   21219           5 :   v8::Isolate* isolate = env->GetIsolate();
   21220          10 :   v8::HandleScope scope(isolate);
   21221             :   { // Check normal properties and defined getters.
   21222             :     Local<Value> value = CompileRun(
   21223             :         "function Foo() {"
   21224             :         "    this.foo = 11;"
   21225             :         "    this.__defineGetter__('baz', function() { return 1; });"
   21226             :         "};"
   21227             :         "function Bar() { "
   21228             :         "    this.bar = 13;"
   21229             :         "    this.__defineGetter__('bla', function() { return 2; });"
   21230             :         "};"
   21231             :         "Bar.prototype = new Foo();"
   21232             :         "new Bar();");
   21233           5 :     CHECK(value->IsObject());
   21234           5 :     Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
   21235          15 :     CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
   21236          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21237          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21238          15 :     CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
   21239          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
   21240          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
   21241             :   }
   21242             :   { // Check named getter interceptors.
   21243           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21244             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21245           5 :         HasOwnPropertyNamedPropertyGetter));
   21246           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21247          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   21248          10 :     CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
   21249          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21250          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21251             :   }
   21252             :   { // Check indexed getter interceptors.
   21253           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21254             :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21255           5 :         HasOwnPropertyIndexedPropertyGetter));
   21256           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21257          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   21258          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   21259          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
   21260          10 :     CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
   21261          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21262             :   }
   21263             :   { // Check named query interceptors.
   21264           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21265             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21266           5 :         0, 0, HasOwnPropertyNamedPropertyQuery));
   21267           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21268          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21269          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21270             :   }
   21271             :   { // Check indexed query interceptors.
   21272           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21273             :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21274           5 :         0, 0, HasOwnPropertyIndexedPropertyQuery));
   21275           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21276          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   21277          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   21278          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
   21279          10 :     CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
   21280             :   }
   21281             :   { // Check callbacks.
   21282           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21283           5 :     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   21284           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21285          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21286          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21287             :   }
   21288             :   { // Check that query wins on disagreement.
   21289           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21290             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21291             :         HasOwnPropertyNamedPropertyGetter, 0,
   21292           5 :         HasOwnPropertyNamedPropertyQuery2));
   21293           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21294          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21295          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21296             :   }
   21297             :   {  // Check that non-internalized keys are handled correctly.
   21298           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21299             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21300           5 :         HasOwnPropertyAccessorNameGetter));
   21301           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21302          25 :     env->Global()->Set(env.local(), v8_str("obj"), instance).FromJust();
   21303             :     const char* src =
   21304             :         "var dyn_string = 'this string ';"
   21305             :         "dyn_string += 'does not exist elsewhere';"
   21306             :         "({}).hasOwnProperty.call(obj, dyn_string)";
   21307          15 :     CHECK(CompileRun(src)->BooleanValue(env.local()).FromJust());
   21308           5 :   }
   21309           5 : }
   21310             : 
   21311             : 
   21312       23723 : TEST(IndexedInterceptorWithStringProto) {
   21313           5 :   v8::Isolate* isolate = CcTest::isolate();
   21314           5 :   v8::HandleScope scope(isolate);
   21315           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21316             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21317           5 :       nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   21318          10 :   LocalContext context;
   21319          30 :   CHECK(context->Global()
   21320             :             ->Set(context.local(), v8_str("obj"),
   21321             :                   templ->NewInstance(context.local()).ToLocalChecked())
   21322             :             .FromJust());
   21323             :   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   21324             :   // These should be intercepted.
   21325          15 :   CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
   21326          15 :   CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
   21327             :   // These should fall through to the String prototype.
   21328          15 :   CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
   21329          15 :   CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
   21330             :   // And these should both fail.
   21331          15 :   CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
   21332          20 :   CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
   21333           5 : }
   21334             : 
   21335             : 
   21336          18 : void CheckCodeGenerationAllowed() {
   21337          18 :   Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   21338             :   Local<Value> result = CompileRun("eval('42')");
   21339          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21340             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   21341          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21342             :   result = CompileRun("var f = new Function('return 42'); f()");
   21343          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21344          18 : }
   21345             : 
   21346             : 
   21347          12 : void CheckCodeGenerationDisallowed() {
   21348          12 :   TryCatch try_catch(CcTest::isolate());
   21349             : 
   21350             :   Local<Value> result = CompileRun("eval('42')");
   21351          12 :   CHECK(result.IsEmpty());
   21352          12 :   CHECK(try_catch.HasCaught());
   21353          12 :   try_catch.Reset();
   21354             : 
   21355             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   21356          12 :   CHECK(result.IsEmpty());
   21357          12 :   CHECK(try_catch.HasCaught());
   21358          12 :   try_catch.Reset();
   21359             : 
   21360             :   result = CompileRun("var f = new Function('return 42'); f()");
   21361          12 :   CHECK(result.IsEmpty());
   21362          12 :   CHECK(try_catch.HasCaught());
   21363          12 : }
   21364             : 
   21365             : char first_fourty_bytes[41];
   21366             : 
   21367          23 : bool CodeGenerationAllowed(Local<Context> context, Local<String> source) {
   21368          23 :   String::Utf8Value str(CcTest::isolate(), source);
   21369             :   size_t len = std::min(sizeof(first_fourty_bytes) - 1,
   21370          46 :                         static_cast<size_t>(str.length()));
   21371          23 :   strncpy(first_fourty_bytes, *str, len);
   21372          23 :   first_fourty_bytes[len] = 0;
   21373          23 :   ApiTestFuzzer::Fuzz();
   21374          23 :   return true;
   21375             : }
   21376             : 
   21377          23 : bool CodeGenerationDisallowed(Local<Context> context, Local<String> source) {
   21378          23 :   ApiTestFuzzer::Fuzz();
   21379          23 :   return false;
   21380             : }
   21381             : 
   21382             : 
   21383       23724 : THREADED_TEST(AllowCodeGenFromStrings) {
   21384           6 :   LocalContext context;
   21385          12 :   v8::HandleScope scope(context->GetIsolate());
   21386             : 
   21387             :   // eval and the Function constructor allowed by default.
   21388           6 :   CHECK(context->IsCodeGenerationFromStringsAllowed());
   21389           6 :   CheckCodeGenerationAllowed();
   21390             : 
   21391             :   // Disallow eval and the Function constructor.
   21392           6 :   context->AllowCodeGenerationFromStrings(false);
   21393           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21394           6 :   CheckCodeGenerationDisallowed();
   21395             : 
   21396             :   // Allow again.
   21397           6 :   context->AllowCodeGenerationFromStrings(true);
   21398           6 :   CheckCodeGenerationAllowed();
   21399             : 
   21400             :   // Disallow but setting a global callback that will allow the calls.
   21401           6 :   context->AllowCodeGenerationFromStrings(false);
   21402             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21403           6 :       &CodeGenerationAllowed);
   21404           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21405           6 :   CheckCodeGenerationAllowed();
   21406             : 
   21407             :   // Set a callback that disallows the code generation.
   21408             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21409           6 :       &CodeGenerationDisallowed);
   21410           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21411          12 :   CheckCodeGenerationDisallowed();
   21412           6 : }
   21413             : 
   21414             : 
   21415       23723 : TEST(SetErrorMessageForCodeGenFromStrings) {
   21416           5 :   LocalContext context;
   21417          10 :   v8::HandleScope scope(context->GetIsolate());
   21418          10 :   TryCatch try_catch(context->GetIsolate());
   21419             : 
   21420           5 :   Local<String> message = v8_str("Message");
   21421           5 :   Local<String> expected_message = v8_str("Uncaught EvalError: Message");
   21422             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21423           5 :       &CodeGenerationDisallowed);
   21424           5 :   context->AllowCodeGenerationFromStrings(false);
   21425           5 :   context->SetErrorMessageForCodeGenerationFromStrings(message);
   21426             :   Local<Value> result = CompileRun("eval('42')");
   21427           5 :   CHECK(result.IsEmpty());
   21428           5 :   CHECK(try_catch.HasCaught());
   21429          10 :   Local<String> actual_message = try_catch.Message()->Get();
   21430          20 :   CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
   21431           5 : }
   21432             : 
   21433       23723 : TEST(CaptureSourceForCodeGenFromStrings) {
   21434           5 :   LocalContext context;
   21435          10 :   v8::HandleScope scope(context->GetIsolate());
   21436          10 :   TryCatch try_catch(context->GetIsolate());
   21437             : 
   21438             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21439           5 :       &CodeGenerationAllowed);
   21440           5 :   context->AllowCodeGenerationFromStrings(false);
   21441             :   CompileRun("eval('42')");
   21442          10 :   CHECK(!strcmp(first_fourty_bytes, "42"));
   21443           5 : }
   21444             : 
   21445           6 : static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21446           6 : }
   21447             : 
   21448             : 
   21449       23724 : THREADED_TEST(CallAPIFunctionOnNonObject) {
   21450           6 :   LocalContext context;
   21451           6 :   v8::Isolate* isolate = context->GetIsolate();
   21452          12 :   v8::HandleScope scope(isolate);
   21453             :   Local<FunctionTemplate> templ =
   21454           6 :       v8::FunctionTemplate::New(isolate, NonObjectThis);
   21455             :   Local<Function> function =
   21456          12 :       templ->GetFunction(context.local()).ToLocalChecked();
   21457          30 :   CHECK(context->Global()
   21458             :             ->Set(context.local(), v8_str("f"), function)
   21459             :             .FromJust());
   21460          12 :   TryCatch try_catch(isolate);
   21461           6 :   CompileRun("f.call(2)");
   21462           6 : }
   21463             : 
   21464             : 
   21465             : // Regression test for issue 1470.
   21466       23724 : THREADED_TEST(ReadOnlyIndexedProperties) {
   21467           6 :   v8::Isolate* isolate = CcTest::isolate();
   21468           6 :   v8::HandleScope scope(isolate);
   21469           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21470             : 
   21471          12 :   LocalContext context;
   21472          12 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   21473          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   21474             :   obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
   21475          24 :                          v8::ReadOnly)
   21476          12 :       .FromJust();
   21477          24 :   obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
   21478          30 :   CHECK(v8_str("DONT_CHANGE")
   21479             :             ->Equals(context.local(),
   21480             :                      obj->Get(context.local(), v8_str("1")).ToLocalChecked())
   21481             :             .FromJust());
   21482             :   obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
   21483          24 :                          v8::ReadOnly)
   21484          12 :       .FromJust();
   21485          18 :   obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
   21486          24 :   CHECK(v8_str("DONT_CHANGE")
   21487             :             ->Equals(context.local(),
   21488             :                      obj->Get(context.local(), v8_num(2)).ToLocalChecked())
   21489             :             .FromJust());
   21490             : 
   21491             :   // Test non-smi case.
   21492             :   obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
   21493          24 :                          v8_str("DONT_CHANGE"), v8::ReadOnly)
   21494          12 :       .FromJust();
   21495          24 :   obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
   21496          30 :   CHECK(v8_str("DONT_CHANGE")
   21497             :             ->Equals(context.local(),
   21498             :                      obj->Get(context.local(), v8_str("2000000000"))
   21499             :                          .ToLocalChecked())
   21500           6 :             .FromJust());
   21501           6 : }
   21502             : 
   21503             : 
   21504          12 : static int CountLiveMapsInMapCache(i::Context* context) {
   21505             :   i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
   21506             :   int length = map_cache->length();
   21507             :   int count = 0;
   21508        1548 :   for (int i = 0; i < length; i++) {
   21509             :     i::Object* value = map_cache->get(i);
   21510        1548 :     if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
   21511             :   }
   21512          12 :   return count;
   21513             : }
   21514             : 
   21515             : 
   21516       23724 : THREADED_TEST(Regress1516) {
   21517           6 :   LocalContext context;
   21518          12 :   v8::HandleScope scope(context->GetIsolate());
   21519             : 
   21520             :   // Object with 20 properties is not a common case, so it should be removed
   21521             :   // from the cache after GC.
   21522           6 :   { v8::HandleScope temp_scope(context->GetIsolate());
   21523             :     CompileRun(
   21524             :         "({"
   21525             :         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
   21526             :         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
   21527             :         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
   21528             :         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
   21529           6 :         "})");
   21530             :   }
   21531             : 
   21532           6 :   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
   21533           6 :   CHECK_LE(1, elements);
   21534             : 
   21535             :   // We have to abort incremental marking here to abandon black pages.
   21536           6 :   CcTest::CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
   21537             : 
   21538          12 :   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
   21539           6 : }
   21540             : 
   21541             : 
   21542       23724 : THREADED_TEST(Regress93759) {
   21543           6 :   v8::Isolate* isolate = CcTest::isolate();
   21544           6 :   HandleScope scope(isolate);
   21545             : 
   21546             :   // Template for object with security check.
   21547           6 :   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
   21548           6 :   no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   21549             : 
   21550             :   // Templates for objects with hidden prototypes and possibly security check.
   21551             :   Local<FunctionTemplate> hidden_proto_template =
   21552           6 :       v8::FunctionTemplate::New(isolate);
   21553           6 :   hidden_proto_template->SetHiddenPrototype(true);
   21554             : 
   21555             :   Local<FunctionTemplate> protected_hidden_proto_template =
   21556           6 :       v8::FunctionTemplate::New(isolate);
   21557             :   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
   21558          12 :       AccessAlwaysBlocked);
   21559           6 :   protected_hidden_proto_template->SetHiddenPrototype(true);
   21560             : 
   21561             :   // Context for "foreign" objects used in test.
   21562           6 :   Local<Context> context = v8::Context::New(isolate);
   21563           6 :   context->Enter();
   21564             : 
   21565             :   // Plain object, no security check.
   21566           6 :   Local<Object> simple_object = Object::New(isolate);
   21567             : 
   21568             :   // Object with explicit security check.
   21569             :   Local<Object> protected_object =
   21570           6 :       no_proto_template->NewInstance(context).ToLocalChecked();
   21571             : 
   21572             :   // JSGlobalProxy object, always have security check.
   21573           6 :   Local<Object> proxy_object = context->Global();
   21574             : 
   21575             :   // Global object, the  prototype of proxy_object. No security checks.
   21576             :   Local<Object> global_object =
   21577          18 :       proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
   21578             : 
   21579             :   // Hidden prototype without security check.
   21580             :   Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
   21581           6 :                                        .ToLocalChecked()
   21582             :                                        ->NewInstance(context)
   21583             :                                        .ToLocalChecked();
   21584             :   Local<Object> object_with_hidden =
   21585           6 :     Object::New(isolate);
   21586          12 :   object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
   21587             : 
   21588           6 :   context->Exit();
   21589             : 
   21590          12 :   LocalContext context2;
   21591           6 :   v8::Local<v8::Object> global = context2->Global();
   21592             : 
   21593             :   // Setup global variables.
   21594          18 :   CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
   21595             :             .FromJust());
   21596          18 :   CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
   21597             :             .FromJust());
   21598          18 :   CHECK(global->Set(context2.local(), v8_str("global"), global_object)
   21599             :             .FromJust());
   21600          18 :   CHECK(
   21601             :       global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
   21602          18 :   CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
   21603             :             .FromJust());
   21604             : 
   21605             :   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   21606          12 :   CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
   21607             :             .FromJust());
   21608             : 
   21609             :   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   21610           6 :   CHECK(result2->IsNull());
   21611             : 
   21612             :   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   21613          12 :   CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
   21614             :             .FromJust());
   21615             : 
   21616             :   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   21617           6 :   CHECK(result4->IsNull());
   21618             : 
   21619             :   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   21620          24 :   CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
   21621             :                                               ->ToObject(context2.local())
   21622             :                                               .ToLocalChecked()
   21623             :                                               ->GetPrototype())
   21624           6 :             .FromJust());
   21625           6 : }
   21626             : 
   21627             : 
   21628          84 : static void TestReceiver(Local<Value> expected_result,
   21629             :                          Local<Value> expected_receiver,
   21630             :                          const char* code) {
   21631             :   Local<Value> result = CompileRun(code);
   21632          84 :   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   21633          84 :   CHECK(result->IsObject());
   21634         252 :   CHECK(expected_receiver
   21635             :             ->Equals(context,
   21636             :                      result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
   21637             :             .FromJust());
   21638         252 :   CHECK(expected_result
   21639             :             ->Equals(context,
   21640             :                      result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
   21641             :             .FromJust());
   21642          84 : }
   21643             : 
   21644             : 
   21645       23724 : THREADED_TEST(ForeignFunctionReceiver) {
   21646           6 :   v8::Isolate* isolate = CcTest::isolate();
   21647           6 :   HandleScope scope(isolate);
   21648             : 
   21649             :   // Create two contexts with different "id" properties ('i' and 'o').
   21650             :   // Call a function both from its own context and from a the foreign
   21651             :   // context, and see what "this" is bound to (returning both "this"
   21652             :   // and "this.id" for comparison).
   21653             : 
   21654           6 :   Local<Context> foreign_context = v8::Context::New(isolate);
   21655           6 :   foreign_context->Enter();
   21656             :   Local<Value> foreign_function =
   21657             :     CompileRun("function func() { return { 0: this.id, "
   21658             :                "                           1: this, "
   21659             :                "                           toString: function() { "
   21660             :                "                               return this[0];"
   21661             :                "                           }"
   21662             :                "                         };"
   21663             :                "}"
   21664             :                "var id = 'i';"
   21665             :                "func;");
   21666           6 :   CHECK(foreign_function->IsFunction());
   21667           6 :   foreign_context->Exit();
   21668             : 
   21669          12 :   LocalContext context;
   21670             : 
   21671           6 :   Local<String> password = v8_str("Password");
   21672             :   // Don't get hit by security checks when accessing foreign_context's
   21673             :   // global receiver (aka. global proxy).
   21674           6 :   context->SetSecurityToken(password);
   21675           6 :   foreign_context->SetSecurityToken(password);
   21676             : 
   21677           6 :   Local<String> i = v8_str("i");
   21678           6 :   Local<String> o = v8_str("o");
   21679           6 :   Local<String> id = v8_str("id");
   21680             : 
   21681             :   CompileRun("function ownfunc() { return { 0: this.id, "
   21682             :              "                              1: this, "
   21683             :              "                              toString: function() { "
   21684             :              "                                  return this[0];"
   21685             :              "                              }"
   21686             :              "                             };"
   21687             :              "}"
   21688             :              "var id = 'o';"
   21689             :              "ownfunc");
   21690          30 :   CHECK(context->Global()
   21691             :             ->Set(context.local(), v8_str("func"), foreign_function)
   21692             :             .FromJust());
   21693             : 
   21694             :   // Sanity check the contexts.
   21695          24 :   CHECK(
   21696             :       i->Equals(
   21697             :            context.local(),
   21698             :            foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
   21699             :           .FromJust());
   21700          30 :   CHECK(o->Equals(context.local(),
   21701             :                   context->Global()->Get(context.local(), id).ToLocalChecked())
   21702             :             .FromJust());
   21703             : 
   21704             :   // Checking local function's receiver.
   21705             :   // Calling function using its call/apply methods.
   21706          12 :   TestReceiver(o, context->Global(), "ownfunc.call()");
   21707          12 :   TestReceiver(o, context->Global(), "ownfunc.apply()");
   21708             :   // Making calls through built-in functions.
   21709          12 :   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   21710          12 :   CHECK(
   21711             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
   21712             :           .FromJust());
   21713          12 :   CHECK(
   21714             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
   21715             :           .FromJust());
   21716          12 :   CHECK(
   21717             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
   21718             :           .FromJust());
   21719             :   // Calling with environment record as base.
   21720          12 :   TestReceiver(o, context->Global(), "ownfunc()");
   21721             :   // Calling with no base.
   21722          12 :   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   21723             : 
   21724             :   // Checking foreign function return value.
   21725             :   // Calling function using its call/apply methods.
   21726          12 :   TestReceiver(i, foreign_context->Global(), "func.call()");
   21727          12 :   TestReceiver(i, foreign_context->Global(), "func.apply()");
   21728             :   // Calling function using another context's call/apply methods.
   21729             :   TestReceiver(i, foreign_context->Global(),
   21730          12 :                "Function.prototype.call.call(func)");
   21731             :   TestReceiver(i, foreign_context->Global(),
   21732          12 :                "Function.prototype.call.apply(func)");
   21733             :   TestReceiver(i, foreign_context->Global(),
   21734          12 :                "Function.prototype.apply.call(func)");
   21735             :   TestReceiver(i, foreign_context->Global(),
   21736          12 :                "Function.prototype.apply.apply(func)");
   21737             :   // Making calls through built-in functions.
   21738          12 :   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   21739             :   // ToString(func()) is func()[0], i.e., the returned this.id.
   21740          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
   21741             :             .FromJust());
   21742          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
   21743             :             .FromJust());
   21744          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
   21745             :             .FromJust());
   21746             : 
   21747             :   // Calling with environment record as base.
   21748          12 :   TestReceiver(i, foreign_context->Global(), "func()");
   21749             :   // Calling with no base.
   21750          18 :   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   21751           6 : }
   21752             : 
   21753             : 
   21754             : uint8_t callback_fired = 0;
   21755             : uint8_t before_call_entered_callback_count1 = 0;
   21756             : uint8_t before_call_entered_callback_count2 = 0;
   21757             : 
   21758             : 
   21759           5 : void CallCompletedCallback1(v8::Isolate*) {
   21760           5 :   v8::base::OS::Print("Firing callback 1.\n");
   21761           5 :   callback_fired ^= 1;  // Toggle first bit.
   21762           5 : }
   21763             : 
   21764             : 
   21765          15 : void CallCompletedCallback2(v8::Isolate*) {
   21766          15 :   v8::base::OS::Print("Firing callback 2.\n");
   21767          15 :   callback_fired ^= 2;  // Toggle second bit.
   21768          15 : }
   21769             : 
   21770             : 
   21771          20 : void BeforeCallEnteredCallback1(v8::Isolate*) {
   21772          20 :   v8::base::OS::Print("Firing before call entered callback 1.\n");
   21773          20 :   before_call_entered_callback_count1++;
   21774          20 : }
   21775             : 
   21776             : 
   21777          60 : void BeforeCallEnteredCallback2(v8::Isolate*) {
   21778          60 :   v8::base::OS::Print("Firing before call entered callback 2.\n");
   21779          60 :   before_call_entered_callback_count2++;
   21780          60 : }
   21781             : 
   21782             : 
   21783          60 : void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21784             :   int32_t level =
   21785         180 :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   21786          60 :   if (level < 3) {
   21787          45 :     level++;
   21788          45 :     v8::base::OS::Print("Entering recursion level %d.\n", level);
   21789             :     char script[64];
   21790             :     i::Vector<char> script_vector(script, sizeof(script));
   21791          45 :     i::SNPrintF(script_vector, "recursion(%d)", level);
   21792             :     CompileRun(script_vector.start());
   21793          45 :     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   21794          90 :     CHECK_EQ(0, callback_fired);
   21795             :   } else {
   21796          15 :     v8::base::OS::Print("Recursion ends.\n");
   21797          30 :     CHECK_EQ(0, callback_fired);
   21798             :   }
   21799          60 : }
   21800             : 
   21801             : 
   21802       23723 : TEST(CallCompletedCallback) {
   21803           5 :   LocalContext env;
   21804          10 :   v8::HandleScope scope(env->GetIsolate());
   21805             :   v8::Local<v8::FunctionTemplate> recursive_runtime =
   21806           5 :       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   21807             :   env->Global()
   21808             :       ->Set(env.local(), v8_str("recursion"),
   21809          30 :             recursive_runtime->GetFunction(env.local()).ToLocalChecked())
   21810          10 :       .FromJust();
   21811             :   // Adding the same callback a second time has no effect.
   21812           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21813           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21814           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   21815           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21816           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
   21817           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21818           5 :   v8::base::OS::Print("--- Script (1) ---\n");
   21819           5 :   callback_fired = 0;
   21820           5 :   before_call_entered_callback_count1 = 0;
   21821           5 :   before_call_entered_callback_count2 = 0;
   21822             :   Local<Script> script =
   21823           5 :       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   21824           5 :   script->Run(env.local()).ToLocalChecked();
   21825          10 :   CHECK_EQ(3, callback_fired);
   21826          10 :   CHECK_EQ(4, before_call_entered_callback_count1);
   21827          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21828             : 
   21829           5 :   v8::base::OS::Print("\n--- Script (2) ---\n");
   21830           5 :   callback_fired = 0;
   21831           5 :   before_call_entered_callback_count1 = 0;
   21832           5 :   before_call_entered_callback_count2 = 0;
   21833           5 :   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   21834             :   env->GetIsolate()->RemoveBeforeCallEnteredCallback(
   21835           5 :       BeforeCallEnteredCallback1);
   21836           5 :   script->Run(env.local()).ToLocalChecked();
   21837          10 :   CHECK_EQ(2, callback_fired);
   21838          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   21839          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21840             : 
   21841           5 :   v8::base::OS::Print("\n--- Function ---\n");
   21842           5 :   callback_fired = 0;
   21843           5 :   before_call_entered_callback_count1 = 0;
   21844           5 :   before_call_entered_callback_count2 = 0;
   21845             :   Local<Function> recursive_function = Local<Function>::Cast(
   21846          25 :       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   21847           5 :   v8::Local<Value> args[] = {v8_num(0)};
   21848          15 :   recursive_function->Call(env.local(), env->Global(), 1, args)
   21849           5 :       .ToLocalChecked();
   21850          10 :   CHECK_EQ(2, callback_fired);
   21851          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   21852          15 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21853           5 : }
   21854             : 
   21855             : 
   21856           5 : void CallCompletedCallbackNoException(v8::Isolate*) {
   21857           5 :   v8::HandleScope scope(CcTest::isolate());
   21858           5 :   CompileRun("1+1;");
   21859           5 : }
   21860             : 
   21861             : 
   21862           5 : void CallCompletedCallbackException(v8::Isolate*) {
   21863           5 :   v8::HandleScope scope(CcTest::isolate());
   21864           5 :   CompileRun("throw 'second exception';");
   21865           5 : }
   21866             : 
   21867             : 
   21868       23723 : TEST(CallCompletedCallbackOneException) {
   21869           5 :   LocalContext env;
   21870          10 :   v8::HandleScope scope(env->GetIsolate());
   21871           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   21872           5 :   CompileRun("throw 'exception';");
   21873           5 : }
   21874             : 
   21875             : 
   21876       23723 : TEST(CallCompletedCallbackTwoExceptions) {
   21877           5 :   LocalContext env;
   21878          10 :   v8::HandleScope scope(env->GetIsolate());
   21879           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   21880           5 :   CompileRun("throw 'first exception';");
   21881           5 : }
   21882             : 
   21883             : 
   21884         135 : static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   21885          45 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21886          45 :   v8::HandleScope scope(info.GetIsolate());
   21887             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21888          90 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21889          45 :   CompileRun("ext1Calls++;");
   21890          45 : }
   21891             : 
   21892             : 
   21893         150 : static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   21894          50 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21895          50 :   v8::HandleScope scope(info.GetIsolate());
   21896             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21897         100 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21898          50 :   CompileRun("ext2Calls++;");
   21899          50 : }
   21900             : 
   21901             : void* g_passed_to_three = nullptr;
   21902             : 
   21903          10 : static void MicrotaskThree(void* data) {
   21904          10 :   g_passed_to_three = data;
   21905          10 : }
   21906             : 
   21907             : 
   21908       23723 : TEST(EnqueueMicrotask) {
   21909           5 :   LocalContext env;
   21910          10 :   v8::HandleScope scope(env->GetIsolate());
   21911           5 :   CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
   21912             :   CompileRun(
   21913             :       "var ext1Calls = 0;"
   21914             :       "var ext2Calls = 0;");
   21915             :   CompileRun("1+1;");
   21916          15 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21917          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21918             : 
   21919             :   env->GetIsolate()->EnqueueMicrotask(
   21920          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21921             :   CompileRun("1+1;");
   21922          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21923          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21924             : 
   21925             :   env->GetIsolate()->EnqueueMicrotask(
   21926          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21927             :   env->GetIsolate()->EnqueueMicrotask(
   21928          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21929             :   CompileRun("1+1;");
   21930          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21931          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21932             : 
   21933             :   env->GetIsolate()->EnqueueMicrotask(
   21934          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21935             :   CompileRun("1+1;");
   21936          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21937          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21938             : 
   21939             :   CompileRun("1+1;");
   21940          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21941          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21942             : 
   21943           5 :   g_passed_to_three = nullptr;
   21944           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   21945             :   CompileRun("1+1;");
   21946           5 :   CHECK(!g_passed_to_three);
   21947          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21948          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21949             : 
   21950             :   int dummy;
   21951             :   env->GetIsolate()->EnqueueMicrotask(
   21952          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21953           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   21954             :   env->GetIsolate()->EnqueueMicrotask(
   21955          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21956             :   CompileRun("1+1;");
   21957           5 :   CHECK_EQ(&dummy, g_passed_to_three);
   21958          15 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21959          15 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21960          10 :   g_passed_to_three = nullptr;
   21961           5 : }
   21962             : 
   21963             : 
   21964           5 : static void MicrotaskExceptionOne(
   21965          10 :     const v8::FunctionCallbackInfo<Value>& info) {
   21966           5 :   v8::HandleScope scope(info.GetIsolate());
   21967             :   CompileRun("exception1Calls++;");
   21968             :   info.GetIsolate()->ThrowException(
   21969          10 :       v8::Exception::Error(v8_str("first")));
   21970           5 : }
   21971             : 
   21972             : 
   21973           5 : static void MicrotaskExceptionTwo(
   21974          10 :     const v8::FunctionCallbackInfo<Value>& info) {
   21975           5 :   v8::HandleScope scope(info.GetIsolate());
   21976             :   CompileRun("exception2Calls++;");
   21977             :   info.GetIsolate()->ThrowException(
   21978          10 :       v8::Exception::Error(v8_str("second")));
   21979           5 : }
   21980             : 
   21981             : 
   21982       23723 : TEST(RunMicrotasksIgnoresThrownExceptions) {
   21983           5 :   LocalContext env;
   21984           5 :   v8::Isolate* isolate = env->GetIsolate();
   21985          10 :   v8::HandleScope scope(isolate);
   21986             :   CompileRun(
   21987             :       "var exception1Calls = 0;"
   21988             :       "var exception2Calls = 0;");
   21989             :   isolate->EnqueueMicrotask(
   21990          10 :       Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
   21991             :   isolate->EnqueueMicrotask(
   21992          10 :       Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
   21993          10 :   TryCatch try_catch(isolate);
   21994             :   CompileRun("1+1;");
   21995           5 :   CHECK(!try_catch.HasCaught());
   21996          15 :   CHECK_EQ(1,
   21997             :            CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
   21998          15 :   CHECK_EQ(1,
   21999           5 :            CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
   22000           5 : }
   22001             : 
   22002             : 
   22003             : uint8_t microtasks_completed_callback_count = 0;
   22004             : 
   22005             : 
   22006          25 : static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
   22007          25 :   ++microtasks_completed_callback_count;
   22008          25 : }
   22009             : 
   22010             : 
   22011       23723 : TEST(SetAutorunMicrotasks) {
   22012           5 :   LocalContext env;
   22013          10 :   v8::HandleScope scope(env->GetIsolate());
   22014             :   env->GetIsolate()->AddMicrotasksCompletedCallback(
   22015           5 :       &MicrotasksCompletedCallback);
   22016             :   CompileRun(
   22017             :       "var ext1Calls = 0;"
   22018             :       "var ext2Calls = 0;");
   22019             :   CompileRun("1+1;");
   22020          15 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22021          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22022           5 :   CHECK_EQ(0u, microtasks_completed_callback_count);
   22023             : 
   22024             :   env->GetIsolate()->EnqueueMicrotask(
   22025          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22026             :   CompileRun("1+1;");
   22027          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22028          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22029           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   22030             : 
   22031           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   22032             :   env->GetIsolate()->EnqueueMicrotask(
   22033          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22034             :   env->GetIsolate()->EnqueueMicrotask(
   22035          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22036             :   CompileRun("1+1;");
   22037          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22038          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22039           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   22040             : 
   22041           5 :   env->GetIsolate()->RunMicrotasks();
   22042          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22043          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22044           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   22045             : 
   22046             :   env->GetIsolate()->EnqueueMicrotask(
   22047          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22048             :   CompileRun("1+1;");
   22049          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22050          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22051           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   22052             : 
   22053           5 :   env->GetIsolate()->RunMicrotasks();
   22054          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22055          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22056           5 :   CHECK_EQ(3u, microtasks_completed_callback_count);
   22057             : 
   22058           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   22059             :   env->GetIsolate()->EnqueueMicrotask(
   22060          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22061             :   CompileRun("1+1;");
   22062          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22063          15 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22064           5 :   CHECK_EQ(4u, microtasks_completed_callback_count);
   22065             : 
   22066             :   env->GetIsolate()->EnqueueMicrotask(
   22067          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22068             :   {
   22069           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   22070             :     CompileRun("1+1;");
   22071          15 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22072          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22073           5 :     CHECK_EQ(4u, microtasks_completed_callback_count);
   22074             :   }
   22075             : 
   22076             :   CompileRun("1+1;");
   22077          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22078          15 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22079           5 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   22080             : 
   22081             :   env->GetIsolate()->RemoveMicrotasksCompletedCallback(
   22082           5 :       &MicrotasksCompletedCallback);
   22083             :   env->GetIsolate()->EnqueueMicrotask(
   22084          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22085             :   CompileRun("1+1;");
   22086          15 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22087          15 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22088          10 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   22089           5 : }
   22090             : 
   22091             : 
   22092       23723 : TEST(RunMicrotasksWithoutEnteringContext) {
   22093           5 :   v8::Isolate* isolate = CcTest::isolate();
   22094           5 :   HandleScope handle_scope(isolate);
   22095           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   22096           5 :   Local<Context> context = Context::New(isolate);
   22097             :   {
   22098             :     Context::Scope context_scope(context);
   22099             :     CompileRun("var ext1Calls = 0;");
   22100             :     isolate->EnqueueMicrotask(
   22101          10 :         Function::New(context, MicrotaskOne).ToLocalChecked());
   22102             :   }
   22103           5 :   isolate->RunMicrotasks();
   22104             :   {
   22105             :     Context::Scope context_scope(context);
   22106          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
   22107             :   }
   22108           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   22109           5 : }
   22110             : 
   22111             : 
   22112       23723 : TEST(ScopedMicrotasks) {
   22113           5 :   LocalContext env;
   22114          10 :   v8::HandleScope handles(env->GetIsolate());
   22115           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
   22116             :   {
   22117             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   22118           5 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   22119             :     env->GetIsolate()->EnqueueMicrotask(
   22120          10 :         Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22121             :     CompileRun(
   22122             :         "var ext1Calls = 0;"
   22123             :         "var ext2Calls = 0;");
   22124             :     CompileRun("1+1;");
   22125          15 :     CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22126          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22127             :     {
   22128             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   22129           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   22130             :       CompileRun("1+1;");
   22131          15 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22132          15 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22133             :       {
   22134             :         v8::MicrotasksScope scope3(env->GetIsolate(),
   22135           5 :                                    v8::MicrotasksScope::kRunMicrotasks);
   22136             :         CompileRun("1+1;");
   22137          15 :         CHECK_EQ(0,
   22138             :                  CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22139          15 :         CHECK_EQ(0,
   22140           5 :                  CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22141             :       }
   22142          15 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22143          15 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22144             :     }
   22145          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22146          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22147             :     env->GetIsolate()->EnqueueMicrotask(
   22148          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22149             :   }
   22150             : 
   22151             :   {
   22152             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22153           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22154          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22155          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22156             :   }
   22157             : 
   22158             :   {
   22159             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   22160           5 :                                v8::MicrotasksScope::kRunMicrotasks);
   22161             :     CompileRun("1+1;");
   22162          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22163          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22164             :     {
   22165             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   22166           5 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   22167             :     }
   22168          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22169          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22170             :   }
   22171             : 
   22172             :   {
   22173             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22174           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22175          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22176          15 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22177             :     env->GetIsolate()->EnqueueMicrotask(
   22178          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22179             :   }
   22180             : 
   22181             :   {
   22182           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   22183             :     {
   22184             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   22185           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   22186             :     }
   22187             :     v8::MicrotasksScope scope3(env->GetIsolate(),
   22188          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   22189          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22190          20 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22191             :   }
   22192             : 
   22193             :   {
   22194             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   22195           5 :                                v8::MicrotasksScope::kRunMicrotasks);
   22196           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22197          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22198          15 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22199             :   }
   22200             : 
   22201             :   {
   22202             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22203           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22204          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22205          15 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22206             :   }
   22207             : 
   22208           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22209             : 
   22210             :   {
   22211             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22212           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22213          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22214          15 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22215             :     env->GetIsolate()->EnqueueMicrotask(
   22216          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22217             :   }
   22218             : 
   22219           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22220             : 
   22221             :   {
   22222             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22223           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22224          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22225          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22226             :   }
   22227             : 
   22228             :   env->GetIsolate()->EnqueueMicrotask(
   22229          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22230             :   {
   22231           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   22232           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22233             :     v8::MicrotasksScope scope2(env->GetIsolate(),
   22234          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   22235          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22236          20 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22237             :   }
   22238             : 
   22239           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22240             : 
   22241             :   {
   22242             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22243           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22244          15 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22245          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22246             :   }
   22247             : 
   22248          10 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   22249           5 : }
   22250             : 
   22251             : namespace {
   22252             : 
   22253             : int probes_counter = 0;
   22254             : int misses_counter = 0;
   22255             : int updates_counter = 0;
   22256             : 
   22257           0 : int* LookupCounter(const char* name) {
   22258           0 :   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
   22259             :     return &probes_counter;
   22260           0 :   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
   22261             :     return &misses_counter;
   22262           0 :   } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
   22263             :     return &updates_counter;
   22264             :   }
   22265           0 :   return nullptr;
   22266             : }
   22267             : 
   22268             : template <typename Stub, typename... Args>
   22269             : void Recompile(Args... args) {
   22270             :   Stub stub(args...);
   22271             :   stub.DeleteStubFromCacheForTesting();
   22272             :   stub.GetCode();
   22273             : }
   22274             : 
   22275             : void RecompileICStubs(i::Isolate* isolate) {
   22276             :   // BUG(5784): We had a list of IC stubs here to recompile. These are now
   22277             :   // builtins and we can't compile them again (easily). Bug 5784 tracks
   22278             :   // our progress in finding another way to do this.
   22279             : }
   22280             : 
   22281             : }  // namespace
   22282             : 
   22283             : #ifdef ENABLE_DISASSEMBLER
   22284             : // FLAG_test_primary_stub_cache and FLAG_test_secondary_stub_cache are read
   22285             : // only when ENABLE_DISASSEMBLER is not defined.
   22286             : 
   22287             : namespace {
   22288             : 
   22289             : const char* kMegamorphicTestProgram =
   22290             :     "function CreateClass(name) {\n"
   22291             :     "  var src = \n"
   22292             :     // Disable constant tracking of "a" field by assigning different Smi values
   22293             :     // twice to ease megamorphic probes counting.
   22294             :     "    `  function ${name}() { this.a = 0; this.a = 1; };` +\n"
   22295             :     "    `  ${name}.prototype.foo = function() {};` +\n"
   22296             :     "    `  ${name};\\n`;\n"
   22297             :     "  return (0, eval)(src);\n"
   22298             :     "}\n"
   22299             :     "function trigger_ics(obj, v) {\n"
   22300             :     "  obj.foo();\n"
   22301             :     "  obj.a = v;\n"
   22302             :     "};\n"
   22303             :     "var objs = [];\n"
   22304             :     "for (var i = 0; i < 50; i++) {\n"
   22305             :     "  var Class = CreateClass('Class' + i);\n"
   22306             :     "  var obj = new Class();\n"
   22307             :     "  objs.push(obj);\n"
   22308             :     "}\n"
   22309             :     "for (var i = 0; i < 1000; i++) {\n"
   22310             :     "  for (var obj of objs) {\n"
   22311             :     "    trigger_ics(obj, 1);\n"
   22312             :     "  }\n"
   22313             :     "}\n";
   22314             : 
   22315             : void TestStubCache(bool primary) {
   22316             :   i::FLAG_native_code_counters = true;
   22317             :   if (primary) {
   22318             :     i::FLAG_test_primary_stub_cache = true;
   22319             :   } else {
   22320             :     i::FLAG_test_secondary_stub_cache = true;
   22321             :   }
   22322             :   i::FLAG_opt = false;
   22323             : 
   22324             :   v8::Isolate::CreateParams create_params;
   22325             :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   22326             :   create_params.counter_lookup_callback = LookupCounter;
   22327             :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   22328             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   22329             : 
   22330             :   {
   22331             :     v8::Isolate::Scope isolate_scope(isolate);
   22332             :     LocalContext env(isolate);
   22333             :     v8::HandleScope scope(isolate);
   22334             : 
   22335             :     // Enforce recompilation of IC stubs that access megamorphic stub cache
   22336             :     // to respect enabled native code counters and stub cache test flags.
   22337             :     RecompileICStubs(i_isolate);
   22338             : 
   22339             :     int initial_probes = probes_counter;
   22340             :     int initial_misses = misses_counter;
   22341             :     int initial_updates = updates_counter;
   22342             :     CompileRun(kMegamorphicTestProgram);
   22343             :     int probes = probes_counter - initial_probes;
   22344             :     int misses = misses_counter - initial_misses;
   22345             :     int updates = updates_counter - initial_updates;
   22346             :     const int kClassesCount = 50;
   22347             :     const int kIterationsCount = 1000;
   22348             :     const int kICKinds = 2;  // LoadIC and StoreIC
   22349             :     CHECK_LE(kClassesCount * kICKinds, updates);
   22350             :     // Check that updates and misses counts are bounded.
   22351             :     // If there are too many updates then most likely the stub cache does not
   22352             :     // work properly.
   22353             :     CHECK_LE(updates, kClassesCount * 2 * kICKinds);
   22354             :     CHECK_LE(kICKinds, misses);
   22355             :     CHECK_LE(misses, kClassesCount * 2 * kICKinds);
   22356             :     // 2 is for PREMONOMORPHIC and MONOMORPHIC states,
   22357             :     // 4 is for POLYMORPHIC states,
   22358             :     // and all the others probes are for MEGAMORPHIC state.
   22359             :     CHECK_EQ((kIterationsCount * kClassesCount - 2 - 4) * kICKinds, probes);
   22360             :   }
   22361             :   isolate->Dispose();
   22362             : }
   22363             : 
   22364             : }  // namespace
   22365             : 
   22366             : UNINITIALIZED_TEST(PrimaryStubCache) {
   22367             :   TestStubCache(true);
   22368             : }
   22369             : 
   22370             : UNINITIALIZED_TEST(SecondaryStubCache) {
   22371             :   TestStubCache(false);
   22372             : }
   22373             : 
   22374             : #endif  // ENABLE_DISASSEMBLER
   22375             : 
   22376             : namespace {
   22377             : 
   22378          35 : void AssertCowElements(bool expected, const char* source) {
   22379             :   Local<Value> object = CompileRun(source);
   22380             :   i::Handle<i::JSObject> array =
   22381             :       i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*object.As<Object>()));
   22382          35 :   CHECK_EQ(expected, array->elements()->IsCowArray());
   22383          35 : }
   22384             : 
   22385             : }  // namespace
   22386             : 
   22387       23723 : TEST(CheckCOWArraysCreatedRuntimeCounter) {
   22388           5 :   LocalContext env;
   22389          10 :   v8::HandleScope scope(env->GetIsolate());
   22390           5 :   AssertCowElements(true, "[1, 2, 3]");
   22391           5 :   AssertCowElements(false, "[[1], 2, 3]");
   22392           5 :   AssertCowElements(true, "[[1], 2, 3][0]");
   22393           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.foo)");
   22394           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.bar)");
   22395           5 :   AssertCowElements(false, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo)");
   22396          10 :   AssertCowElements(true, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo[3])");
   22397           5 : }
   22398             : 
   22399             : 
   22400       23723 : TEST(StaticGetters) {
   22401           5 :   LocalContext context;
   22402             :   i::Factory* factory = CcTest::i_isolate()->factory();
   22403           5 :   v8::Isolate* isolate = CcTest::isolate();
   22404          10 :   v8::HandleScope scope(isolate);
   22405             :   i::Handle<i::Object> undefined_value = factory->undefined_value();
   22406           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   22407             :   i::Handle<i::Object> null_value = factory->null_value();
   22408           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   22409             :   i::Handle<i::Object> true_value = factory->true_value();
   22410           5 :   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   22411             :   i::Handle<i::Object> false_value = factory->false_value();
   22412          10 :   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   22413           5 : }
   22414             : 
   22415             : 
   22416       23723 : UNINITIALIZED_TEST(IsolateEmbedderData) {
   22417           5 :   CcTest::DisableAutomaticDispose();
   22418             :   v8::Isolate::CreateParams create_params;
   22419           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   22420           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   22421           5 :   isolate->Enter();
   22422             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   22423          25 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22424          20 :     CHECK(!isolate->GetData(slot));
   22425          20 :     CHECK(!i_isolate->GetData(slot));
   22426             :   }
   22427          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22428          20 :     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   22429             :     isolate->SetData(slot, data);
   22430             :   }
   22431          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22432          20 :     void* data = reinterpret_cast<void*>(0xacce55ed + slot);
   22433          20 :     CHECK_EQ(data, isolate->GetData(slot));
   22434          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   22435             :   }
   22436          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22437          20 :     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   22438             :     isolate->SetData(slot, data);
   22439             :   }
   22440          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22441          20 :     void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
   22442          20 :     CHECK_EQ(data, isolate->GetData(slot));
   22443          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   22444             :   }
   22445           5 :   isolate->Exit();
   22446           5 :   isolate->Dispose();
   22447           5 : }
   22448             : 
   22449             : 
   22450       23723 : TEST(StringEmpty) {
   22451           5 :   LocalContext context;
   22452             :   i::Factory* factory = CcTest::i_isolate()->factory();
   22453           5 :   v8::Isolate* isolate = CcTest::isolate();
   22454          10 :   v8::HandleScope scope(isolate);
   22455             :   i::Handle<i::Object> empty_string = factory->empty_string();
   22456          10 :   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   22457           5 : }
   22458             : 
   22459             : 
   22460             : static int instance_checked_getter_count = 0;
   22461         120 : static void InstanceCheckedGetter(
   22462             :     Local<String> name,
   22463             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   22464         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   22465             :             .FromJust());
   22466         120 :   instance_checked_getter_count++;
   22467         120 :   info.GetReturnValue().Set(v8_num(11));
   22468         120 : }
   22469             : 
   22470             : 
   22471             : static int instance_checked_setter_count = 0;
   22472         120 : static void InstanceCheckedSetter(Local<String> name,
   22473             :                       Local<Value> value,
   22474             :                       const v8::PropertyCallbackInfo<void>& info) {
   22475         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   22476             :             .FromJust());
   22477         480 :   CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
   22478             :             .FromJust());
   22479         120 :   instance_checked_setter_count++;
   22480         120 : }
   22481             : 
   22482             : 
   22483         420 : static void CheckInstanceCheckedResult(int getters, int setters,
   22484             :                                        bool expects_callbacks,
   22485             :                                        TryCatch* try_catch) {
   22486         420 :   if (expects_callbacks) {
   22487         240 :     CHECK(!try_catch->HasCaught());
   22488         240 :     CHECK_EQ(getters, instance_checked_getter_count);
   22489         240 :     CHECK_EQ(setters, instance_checked_setter_count);
   22490             :   } else {
   22491         180 :     CHECK(try_catch->HasCaught());
   22492         180 :     CHECK_EQ(0, instance_checked_getter_count);
   22493         180 :     CHECK_EQ(0, instance_checked_setter_count);
   22494             :   }
   22495         420 :   try_catch->Reset();
   22496         420 : }
   22497             : 
   22498             : 
   22499          42 : static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   22500          42 :   instance_checked_getter_count = 0;
   22501          42 :   instance_checked_setter_count = 0;
   22502          42 :   TryCatch try_catch(CcTest::isolate());
   22503             : 
   22504             :   // Test path through generic runtime code.
   22505             :   CompileRun("obj.foo");
   22506          42 :   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   22507             :   CompileRun("obj.foo = 23");
   22508          42 :   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   22509             : 
   22510             :   // Test path through generated LoadIC and StoredIC.
   22511             :   CompileRun("function test_get(o) { o.foo; }"
   22512             :              "test_get(obj);");
   22513          42 :   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   22514             :   CompileRun("test_get(obj);");
   22515          42 :   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   22516             :   CompileRun("test_get(obj);");
   22517          42 :   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   22518             :   CompileRun("function test_set(o) { o.foo = 23; }"
   22519             :              "test_set(obj);");
   22520          42 :   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   22521             :   CompileRun("test_set(obj);");
   22522          42 :   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   22523             :   CompileRun("test_set(obj);");
   22524          42 :   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   22525             : 
   22526             :   // Test path through optimized code.
   22527             :   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   22528             :              "test_get(obj);");
   22529          42 :   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   22530             :   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   22531             :              "test_set(obj);");
   22532          42 :   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   22533             : 
   22534             :   // Cleanup so that closures start out fresh in next check.
   22535             :   CompileRun(
   22536             :       "%DeoptimizeFunction(test_get);"
   22537             :       "%ClearFunctionFeedback(test_get);"
   22538             :       "%DeoptimizeFunction(test_set);"
   22539          42 :       "%ClearFunctionFeedback(test_set);");
   22540          42 : }
   22541             : 
   22542             : 
   22543       23724 : THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   22544           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22545           6 :   LocalContext context;
   22546          12 :   v8::HandleScope scope(context->GetIsolate());
   22547             : 
   22548           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22549           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22550             :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22551             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22552          18 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22553          36 :   CHECK(context->Global()
   22554             :             ->Set(context.local(), v8_str("f"),
   22555             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22556             :             .FromJust());
   22557             : 
   22558             :   printf("Testing positive ...\n");
   22559             :   CompileRun("var obj = new f();");
   22560          30 :   CHECK(templ->HasInstance(
   22561             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22562           6 :   CheckInstanceCheckedAccessors(true);
   22563             : 
   22564             :   printf("Testing negative ...\n");
   22565             :   CompileRun("var obj = {};"
   22566             :              "obj.__proto__ = new f();");
   22567          30 :   CHECK(!templ->HasInstance(
   22568             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22569          12 :   CheckInstanceCheckedAccessors(false);
   22570           6 : }
   22571             : 
   22572             : 
   22573          90 : static void EmptyInterceptorGetter(
   22574          90 :     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22575             : 
   22576             : 
   22577          30 : static void EmptyInterceptorSetter(
   22578             :     Local<String> name, Local<Value> value,
   22579          30 :     const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22580             : 
   22581             : 
   22582       23724 : THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   22583           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22584           6 :   LocalContext context;
   22585          12 :   v8::HandleScope scope(context->GetIsolate());
   22586             : 
   22587           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22588           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22589             :   templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
   22590          12 :                                                      EmptyInterceptorSetter);
   22591             :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22592             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22593          18 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22594          36 :   CHECK(context->Global()
   22595             :             ->Set(context.local(), v8_str("f"),
   22596             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22597             :             .FromJust());
   22598             : 
   22599             :   printf("Testing positive ...\n");
   22600             :   CompileRun("var obj = new f();");
   22601          30 :   CHECK(templ->HasInstance(
   22602             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22603           6 :   CheckInstanceCheckedAccessors(true);
   22604             : 
   22605             :   printf("Testing negative ...\n");
   22606             :   CompileRun("var obj = {};"
   22607             :              "obj.__proto__ = new f();");
   22608          30 :   CHECK(!templ->HasInstance(
   22609             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22610          12 :   CheckInstanceCheckedAccessors(false);
   22611           6 : }
   22612             : 
   22613             : 
   22614       23724 : THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   22615           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22616           6 :   LocalContext context;
   22617          12 :   v8::HandleScope scope(context->GetIsolate());
   22618             : 
   22619           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22620           6 :   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   22621             :   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   22622             :                      InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
   22623             :                      v8::None,
   22624          18 :                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   22625          36 :   CHECK(context->Global()
   22626             :             ->Set(context.local(), v8_str("f"),
   22627             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22628             :             .FromJust());
   22629             : 
   22630             :   printf("Testing positive ...\n");
   22631             :   CompileRun("var obj = new f();");
   22632          30 :   CHECK(templ->HasInstance(
   22633             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22634           6 :   CheckInstanceCheckedAccessors(true);
   22635             : 
   22636             :   printf("Testing negative ...\n");
   22637             :   CompileRun("var obj = {};"
   22638             :              "obj.__proto__ = new f();");
   22639          30 :   CHECK(!templ->HasInstance(
   22640             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22641           6 :   CheckInstanceCheckedAccessors(false);
   22642             : 
   22643             :   printf("Testing positive with modified prototype chain ...\n");
   22644             :   CompileRun("var obj = new f();"
   22645             :              "var pro = {};"
   22646             :              "pro.__proto__ = obj.__proto__;"
   22647             :              "obj.__proto__ = pro;");
   22648          30 :   CHECK(templ->HasInstance(
   22649             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22650          12 :   CheckInstanceCheckedAccessors(true);
   22651           6 : }
   22652             : 
   22653             : 
   22654       23723 : TEST(TryFinallyMessage) {
   22655           5 :   LocalContext context;
   22656          10 :   v8::HandleScope scope(context->GetIsolate());
   22657             :   {
   22658             :     // Test that the original error message is not lost if there is a
   22659             :     // recursive call into Javascript is done in the finally block, e.g. to
   22660             :     // initialize an IC. (crbug.com/129171)
   22661           5 :     TryCatch try_catch(context->GetIsolate());
   22662             :     const char* trigger_ic =
   22663             :         "try {                      \n"
   22664             :         "  throw new Error('test'); \n"
   22665             :         "} finally {                \n"
   22666             :         "  var x = 0;               \n"
   22667             :         "  x++;                     \n"  // Trigger an IC initialization here.
   22668             :         "}                          \n";
   22669             :     CompileRun(trigger_ic);
   22670           5 :     CHECK(try_catch.HasCaught());
   22671           5 :     Local<Message> message = try_catch.Message();
   22672           5 :     CHECK(!message.IsEmpty());
   22673          10 :     CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   22674             :   }
   22675             : 
   22676             :   {
   22677             :     // Test that the original exception message is indeed overwritten if
   22678             :     // a new error is thrown in the finally block.
   22679           5 :     TryCatch try_catch(context->GetIsolate());
   22680             :     const char* throw_again =
   22681             :         "try {                       \n"
   22682             :         "  throw new Error('test');  \n"
   22683             :         "} finally {                 \n"
   22684             :         "  var x = 0;                \n"
   22685             :         "  x++;                      \n"
   22686             :         "  throw new Error('again'); \n"  // This is the new uncaught error.
   22687             :         "}                           \n";
   22688             :     CompileRun(throw_again);
   22689           5 :     CHECK(try_catch.HasCaught());
   22690           5 :     Local<Message> message = try_catch.Message();
   22691           5 :     CHECK(!message.IsEmpty());
   22692          10 :     CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
   22693           5 :   }
   22694           5 : }
   22695             : 
   22696             : 
   22697          96 : static void Helper137002(bool do_store,
   22698             :                          bool polymorphic,
   22699             :                          bool remove_accessor,
   22700             :                          bool interceptor) {
   22701          96 :   LocalContext context;
   22702          96 :   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   22703          96 :   if (interceptor) {
   22704             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
   22705          48 :                                                             FooSetInterceptor));
   22706             :   } else {
   22707             :     templ->SetAccessor(v8_str("foo"),
   22708             :                        GetterWhichReturns42,
   22709          48 :                        SetterWhichSetsYOnThisTo23);
   22710             :   }
   22711         576 :   CHECK(context->Global()
   22712             :             ->Set(context.local(), v8_str("obj"),
   22713             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22714             :             .FromJust());
   22715             : 
   22716             :   // Turn monomorphic on slow object with native accessor, then turn
   22717             :   // polymorphic, finally optimize to create negative lookup and fail.
   22718             :   CompileRun(do_store ?
   22719             :              "function f(x) { x.foo = void 0; }" :
   22720          96 :              "function f(x) { return x.foo; }");
   22721             :   CompileRun("obj.y = void 0;");
   22722          96 :   if (!interceptor) {
   22723             :     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   22724             :   }
   22725             :   CompileRun("obj.__proto__ = null;"
   22726             :              "f(obj); f(obj); f(obj);");
   22727          96 :   if (polymorphic) {
   22728             :     CompileRun("f({});");
   22729             :   }
   22730             :   CompileRun("obj.y = void 0;"
   22731             :              "%OptimizeFunctionOnNextCall(f);");
   22732          96 :   if (remove_accessor) {
   22733             :     CompileRun("delete obj.foo;");
   22734             :   }
   22735             :   CompileRun("var result = f(obj);");
   22736          96 :   if (do_store) {
   22737             :     CompileRun("result = obj.y;");
   22738             :   }
   22739          96 :   if (remove_accessor && !interceptor) {
   22740         120 :     CHECK(context->Global()
   22741             :               ->Get(context.local(), v8_str("result"))
   22742             :               .ToLocalChecked()
   22743             :               ->IsUndefined());
   22744             :   } else {
   22745         432 :     CHECK_EQ(do_store ? 23 : 42, context->Global()
   22746             :                                      ->Get(context.local(), v8_str("result"))
   22747             :                                      .ToLocalChecked()
   22748             :                                      ->Int32Value(context.local())
   22749             :                                      .FromJust());
   22750          96 :   }
   22751          96 : }
   22752             : 
   22753             : 
   22754       23724 : THREADED_TEST(Regress137002a) {
   22755           6 :   i::FLAG_allow_natives_syntax = true;
   22756           6 :   i::FLAG_compilation_cache = false;
   22757           6 :   v8::HandleScope scope(CcTest::isolate());
   22758         102 :   for (int i = 0; i < 16; i++) {
   22759          96 :     Helper137002(i & 8, i & 4, i & 2, i & 1);
   22760           6 :   }
   22761           6 : }
   22762             : 
   22763             : 
   22764       23724 : THREADED_TEST(Regress137002b) {
   22765           6 :   i::FLAG_allow_natives_syntax = true;
   22766           6 :   LocalContext context;
   22767           6 :   v8::Isolate* isolate = context->GetIsolate();
   22768          12 :   v8::HandleScope scope(isolate);
   22769           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22770             :   templ->SetAccessor(v8_str("foo"),
   22771             :                      GetterWhichReturns42,
   22772           6 :                      SetterWhichSetsYOnThisTo23);
   22773          36 :   CHECK(context->Global()
   22774             :             ->Set(context.local(), v8_str("obj"),
   22775             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22776             :             .FromJust());
   22777             : 
   22778             :   // Turn monomorphic on slow object with native accessor, then just
   22779             :   // delete the property and fail.
   22780             :   CompileRun("function load(x) { return x.foo; }"
   22781             :              "function store(x) { x.foo = void 0; }"
   22782             :              "function keyed_load(x, key) { return x[key]; }"
   22783             :              // Second version of function has a different source (add void 0)
   22784             :              // so that it does not share code with the first version.  This
   22785             :              // ensures that the ICs are monomorphic.
   22786             :              "function load2(x) { void 0; return x.foo; }"
   22787             :              "function store2(x) { void 0; x.foo = void 0; }"
   22788             :              "function keyed_load2(x, key) { void 0; return x[key]; }"
   22789             : 
   22790             :              "obj.y = void 0;"
   22791             :              "obj.__proto__ = null;"
   22792             :              "var subobj = {};"
   22793             :              "subobj.y = void 0;"
   22794             :              "subobj.__proto__ = obj;"
   22795             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22796             : 
   22797             :              // Make the ICs monomorphic.
   22798             :              "load(obj); load(obj);"
   22799             :              "load2(subobj); load2(subobj);"
   22800             :              "store(obj); store(obj);"
   22801             :              "store2(subobj); store2(subobj);"
   22802             :              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   22803             :              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   22804             : 
   22805             :              // Actually test the shiny new ICs and better not crash. This
   22806             :              // serves as a regression test for issue 142088 as well.
   22807             :              "load(obj);"
   22808             :              "load2(subobj);"
   22809             :              "store(obj);"
   22810             :              "store2(subobj);"
   22811             :              "keyed_load(obj, 'foo');"
   22812             :              "keyed_load2(subobj, 'foo');"
   22813             : 
   22814             :              // Delete the accessor.  It better not be called any more now.
   22815             :              "delete obj.foo;"
   22816             :              "obj.y = void 0;"
   22817             :              "subobj.y = void 0;"
   22818             : 
   22819             :              "var load_result = load(obj);"
   22820             :              "var load_result2 = load2(subobj);"
   22821             :              "var keyed_load_result = keyed_load(obj, 'foo');"
   22822             :              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   22823             :              "store(obj);"
   22824             :              "store2(subobj);"
   22825             :              "var y_from_obj = obj.y;"
   22826             :              "var y_from_subobj = subobj.y;");
   22827          30 :   CHECK(context->Global()
   22828             :             ->Get(context.local(), v8_str("load_result"))
   22829             :             .ToLocalChecked()
   22830             :             ->IsUndefined());
   22831          30 :   CHECK(context->Global()
   22832             :             ->Get(context.local(), v8_str("load_result2"))
   22833             :             .ToLocalChecked()
   22834             :             ->IsUndefined());
   22835          30 :   CHECK(context->Global()
   22836             :             ->Get(context.local(), v8_str("keyed_load_result"))
   22837             :             .ToLocalChecked()
   22838             :             ->IsUndefined());
   22839          30 :   CHECK(context->Global()
   22840             :             ->Get(context.local(), v8_str("keyed_load_result2"))
   22841             :             .ToLocalChecked()
   22842             :             ->IsUndefined());
   22843          30 :   CHECK(context->Global()
   22844             :             ->Get(context.local(), v8_str("y_from_obj"))
   22845             :             .ToLocalChecked()
   22846             :             ->IsUndefined());
   22847          30 :   CHECK(context->Global()
   22848             :             ->Get(context.local(), v8_str("y_from_subobj"))
   22849             :             .ToLocalChecked()
   22850           6 :             ->IsUndefined());
   22851           6 : }
   22852             : 
   22853             : 
   22854       23724 : THREADED_TEST(Regress142088) {
   22855           6 :   i::FLAG_allow_natives_syntax = true;
   22856           6 :   LocalContext context;
   22857           6 :   v8::Isolate* isolate = context->GetIsolate();
   22858          12 :   v8::HandleScope scope(isolate);
   22859           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22860             :   templ->SetAccessor(v8_str("foo"),
   22861             :                      GetterWhichReturns42,
   22862           6 :                      SetterWhichSetsYOnThisTo23);
   22863          36 :   CHECK(context->Global()
   22864             :             ->Set(context.local(), v8_str("obj"),
   22865             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22866             :             .FromJust());
   22867             : 
   22868             :   CompileRun("function load(x) { return x.foo; }"
   22869             :              "var o = Object.create(obj);"
   22870             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22871           6 :              "load(o); load(o); load(o); load(o);");
   22872           6 : }
   22873             : 
   22874             : 
   22875       23724 : THREADED_TEST(Regress137496) {
   22876           6 :   i::FLAG_expose_gc = true;
   22877           6 :   LocalContext context;
   22878          12 :   v8::HandleScope scope(context->GetIsolate());
   22879             : 
   22880             :   // Compile a try-finally clause where the finally block causes a GC
   22881             :   // while there still is a message pending for external reporting.
   22882          12 :   TryCatch try_catch(context->GetIsolate());
   22883           6 :   try_catch.SetVerbose(true);
   22884             :   CompileRun("try { throw new Error(); } finally { gc(); }");
   22885          12 :   CHECK(try_catch.HasCaught());
   22886           6 : }
   22887             : 
   22888             : 
   22889       23724 : THREADED_TEST(Regress157124) {
   22890           6 :   LocalContext context;
   22891           6 :   v8::Isolate* isolate = context->GetIsolate();
   22892          12 :   v8::HandleScope scope(isolate);
   22893           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22894          12 :   Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   22895           6 :   obj->GetIdentityHash();
   22896             :   obj->DeletePrivate(context.local(),
   22897           6 :                      v8::Private::ForApi(isolate, v8_str("Bug")))
   22898          18 :       .FromJust();
   22899           6 : }
   22900             : 
   22901             : 
   22902       23724 : THREADED_TEST(Regress2535) {
   22903           6 :   LocalContext context;
   22904          12 :   v8::HandleScope scope(context->GetIsolate());
   22905             :   Local<Value> set_value = CompileRun("new Set();");
   22906             :   Local<Object> set_object(Local<Object>::Cast(set_value));
   22907           6 :   CHECK_EQ(0, set_object->InternalFieldCount());
   22908             :   Local<Value> map_value = CompileRun("new Map();");
   22909             :   Local<Object> map_object(Local<Object>::Cast(map_value));
   22910          12 :   CHECK_EQ(0, map_object->InternalFieldCount());
   22911           6 : }
   22912             : 
   22913             : 
   22914       23724 : THREADED_TEST(Regress2746) {
   22915           6 :   LocalContext context;
   22916           6 :   v8::Isolate* isolate = context->GetIsolate();
   22917          12 :   v8::HandleScope scope(isolate);
   22918           6 :   Local<Object> obj = Object::New(isolate);
   22919           6 :   Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
   22920          12 :   CHECK(
   22921             :       obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
   22922           6 :   Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
   22923           6 :   CHECK(!value.IsEmpty());
   22924          12 :   CHECK(value->IsUndefined());
   22925           6 : }
   22926             : 
   22927             : 
   22928       23724 : THREADED_TEST(Regress260106) {
   22929           6 :   LocalContext context;
   22930           6 :   v8::Isolate* isolate = context->GetIsolate();
   22931          12 :   v8::HandleScope scope(isolate);
   22932             :   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   22933           6 :                                                         DummyCallHandler);
   22934             :   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   22935             :   Local<Function> function =
   22936          12 :       templ->GetFunction(context.local()).ToLocalChecked();
   22937           6 :   CHECK(!function.IsEmpty());
   22938          12 :   CHECK(function->IsFunction());
   22939           6 : }
   22940             : 
   22941       23724 : THREADED_TEST(JSONParseObject) {
   22942           6 :   LocalContext context;
   22943          12 :   HandleScope scope(context->GetIsolate());
   22944             :   Local<Value> obj =
   22945          12 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22946           6 :   Local<Object> global = context->Global();
   22947          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22948          12 :   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   22949           6 : }
   22950             : 
   22951       23724 : THREADED_TEST(JSONParseNumber) {
   22952           6 :   LocalContext context;
   22953          12 :   HandleScope scope(context->GetIsolate());
   22954             :   Local<Value> obj =
   22955          12 :       v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
   22956           6 :   Local<Object> global = context->Global();
   22957          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22958          12 :   ExpectString("JSON.stringify(obj)", "42");
   22959           6 : }
   22960             : 
   22961             : namespace {
   22962          42 : void TestJSONParseArray(Local<Context> context, const char* input_str,
   22963             :                         const char* expected_output_str,
   22964             :                         i::ElementsKind expected_elements_kind) {
   22965             :   Local<Value> obj =
   22966          42 :       v8::JSON::Parse(context, v8_str(input_str)).ToLocalChecked();
   22967             : 
   22968             :   i::Handle<i::JSArray> a =
   22969             :       i::Handle<i::JSArray>::cast(v8::Utils::OpenHandle(*obj));
   22970          42 :   CHECK_EQ(expected_elements_kind, a->GetElementsKind());
   22971             : 
   22972          42 :   Local<Object> global = context->Global();
   22973         126 :   global->Set(context, v8_str("obj"), obj).FromJust();
   22974          42 :   ExpectString("JSON.stringify(obj)", expected_output_str);
   22975          42 : }
   22976             : }  // namespace
   22977             : 
   22978       23724 : THREADED_TEST(JSONParseArray) {
   22979           6 :   LocalContext context;
   22980          12 :   HandleScope scope(context->GetIsolate());
   22981             : 
   22982             :   TestJSONParseArray(context.local(), "[0, 1, 2]", "[0,1,2]",
   22983           6 :                      i::PACKED_SMI_ELEMENTS);
   22984             :   TestJSONParseArray(context.local(), "[0, 1.2, 2]", "[0,1.2,2]",
   22985           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   22986             :   TestJSONParseArray(context.local(), "[0.2, 1, 2]", "[0.2,1,2]",
   22987           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   22988             :   TestJSONParseArray(context.local(), "[0, \"a\", 2]", "[0,\"a\",2]",
   22989           6 :                      i::PACKED_ELEMENTS);
   22990             :   TestJSONParseArray(context.local(), "[\"a\", 1, 2]", "[\"a\",1,2]",
   22991           6 :                      i::PACKED_ELEMENTS);
   22992             :   TestJSONParseArray(context.local(), "[\"a\", 1.2, 2]", "[\"a\",1.2,2]",
   22993           6 :                      i::PACKED_ELEMENTS);
   22994             :   TestJSONParseArray(context.local(), "[0, 1.2, \"a\"]", "[0,1.2,\"a\"]",
   22995          12 :                      i::PACKED_ELEMENTS);
   22996           6 : }
   22997             : 
   22998       23724 : THREADED_TEST(JSONStringifyObject) {
   22999           6 :   LocalContext context;
   23000          12 :   HandleScope scope(context->GetIsolate());
   23001             :   Local<Value> value =
   23002           6 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   23003           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   23004           6 :   Local<Object> global = context->Global();
   23005          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   23006             :   Local<String> json =
   23007          12 :       v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
   23008          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   23009          12 :   ExpectString("JSON.stringify(obj)", *utf8);
   23010           6 : }
   23011             : 
   23012       23724 : THREADED_TEST(JSONStringifyObjectWithGap) {
   23013           6 :   LocalContext context;
   23014          12 :   HandleScope scope(context->GetIsolate());
   23015             :   Local<Value> value =
   23016           6 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   23017           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   23018           6 :   Local<Object> global = context->Global();
   23019          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   23020             :   Local<String> json =
   23021          18 :       v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
   23022          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   23023          12 :   ExpectString("JSON.stringify(obj, null,  '*')", *utf8);
   23024           6 : }
   23025             : 
   23026             : #if V8_OS_POSIX
   23027             : class ThreadInterruptTest {
   23028             :  public:
   23029           6 :   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   23030           6 :   ~ThreadInterruptTest() {}
   23031             : 
   23032           6 :   void RunTest() {
   23033             :     InterruptThread i_thread(this);
   23034           6 :     i_thread.Start();
   23035             : 
   23036           6 :     sem_.Wait();
   23037           6 :     CHECK_EQ(kExpectedValue, sem_value_);
   23038           6 :   }
   23039             : 
   23040             :  private:
   23041             :   static const int kExpectedValue = 1;
   23042             : 
   23043           6 :   class InterruptThread : public v8::base::Thread {
   23044             :    public:
   23045             :     explicit InterruptThread(ThreadInterruptTest* test)
   23046           6 :         : Thread(Options("InterruptThread")), test_(test) {}
   23047             : 
   23048           6 :     virtual void Run() {
   23049             :       struct sigaction action;
   23050             : 
   23051             :       // Ensure that we'll enter waiting condition
   23052           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   23053             : 
   23054             :       // Setup signal handler
   23055             :       memset(&action, 0, sizeof(action));
   23056           6 :       action.sa_handler = SignalHandler;
   23057           6 :       sigaction(SIGCHLD, &action, nullptr);
   23058             : 
   23059             :       // Send signal
   23060           6 :       kill(getpid(), SIGCHLD);
   23061             : 
   23062             :       // Ensure that if wait has returned because of error
   23063           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   23064             : 
   23065             :       // Set value and signal semaphore
   23066           6 :       test_->sem_value_ = 1;
   23067           6 :       test_->sem_.Signal();
   23068           6 :     }
   23069             : 
   23070           6 :     static void SignalHandler(int signal) {
   23071           6 :     }
   23072             : 
   23073             :    private:
   23074             :      ThreadInterruptTest* test_;
   23075             :   };
   23076             : 
   23077             :   v8::base::Semaphore sem_;
   23078             :   volatile int sem_value_;
   23079             : };
   23080             : 
   23081             : 
   23082       23724 : THREADED_TEST(SemaphoreInterruption) {
   23083          12 :   ThreadInterruptTest().RunTest();
   23084           6 : }
   23085             : 
   23086             : 
   23087             : #endif  // V8_OS_POSIX
   23088             : 
   23089             : 
   23090           0 : void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   23091           0 :   CHECK(false);
   23092             : }
   23093             : 
   23094             : 
   23095       23723 : TEST(JSONStringifyAccessCheck) {
   23096           5 :   v8::V8::Initialize();
   23097           5 :   v8::Isolate* isolate = CcTest::isolate();
   23098           5 :   v8::HandleScope scope(isolate);
   23099             : 
   23100             :   // Create an ObjectTemplate for global objects and install access
   23101             :   // check callbacks that will block access.
   23102             :   v8::Local<v8::ObjectTemplate> global_template =
   23103           5 :       v8::ObjectTemplate::New(isolate);
   23104           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   23105             : 
   23106             :   // Create a context and set an x property on it's global object.
   23107          10 :   LocalContext context0(nullptr, global_template);
   23108           5 :   v8::Local<v8::Object> global0 = context0->Global();
   23109          15 :   global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
   23110           5 :   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   23111             : 
   23112          15 :   for (int i = 0; i < 2; i++) {
   23113          10 :     if (i == 1) {
   23114             :       // Install a toJSON function on the second run.
   23115             :       v8::Local<v8::FunctionTemplate> toJSON =
   23116           5 :           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   23117             : 
   23118             :       global0->Set(context0.local(), v8_str("toJSON"),
   23119          25 :                    toJSON->GetFunction(context0.local()).ToLocalChecked())
   23120          10 :           .FromJust();
   23121             :     }
   23122             :     // Create a context with a different security token so that the
   23123             :     // failed access check callback will be called on each access.
   23124          10 :     LocalContext context1(nullptr, global_template);
   23125          50 :     CHECK(context1->Global()
   23126             :               ->Set(context1.local(), v8_str("other"), global0)
   23127             :               .FromJust());
   23128             : 
   23129          10 :     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   23130          10 :     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   23131          10 :     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   23132          15 :   }
   23133           5 : }
   23134             : 
   23135             : 
   23136             : bool access_check_fail_thrown = false;
   23137             : bool catch_callback_called = false;
   23138             : 
   23139             : 
   23140             : // Failed access check callback that performs a GC on each invocation.
   23141          80 : void FailedAccessCheckThrows(Local<v8::Object> target,
   23142             :                              v8::AccessType type,
   23143             :                              Local<v8::Value> data) {
   23144          80 :   access_check_fail_thrown = true;
   23145          80 :   i::PrintF("Access check failed. Error thrown.\n");
   23146             :   CcTest::isolate()->ThrowException(
   23147          80 :       v8::Exception::Error(v8_str("cross context")));
   23148          80 : }
   23149             : 
   23150             : 
   23151         300 : void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   23152         300 :   for (int i = 0; i < args.Length(); i++) {
   23153          75 :     i::PrintF("%s\n", *String::Utf8Value(args.GetIsolate(), args[i]));
   23154             :   }
   23155          75 :   catch_callback_called = true;
   23156          75 : }
   23157             : 
   23158             : 
   23159           5 : void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   23160           5 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   23161          20 :   CHECK(
   23162             :       args[0]
   23163             :           ->ToObject(context)
   23164             :           .ToLocalChecked()
   23165             :           ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
   23166             :           .IsNothing());
   23167           5 : }
   23168             : 
   23169             : 
   23170          75 : void CheckCorrectThrow(const char* script) {
   23171             :   // Test that the script, when wrapped into a try-catch, triggers the catch
   23172             :   // clause due to failed access check throwing an exception.
   23173             :   // The subsequent try-catch should run without any exception.
   23174          75 :   access_check_fail_thrown = false;
   23175          75 :   catch_callback_called = false;
   23176             :   i::ScopedVector<char> source(1024);
   23177          75 :   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   23178             :   CompileRun(source.start());
   23179          75 :   CHECK(access_check_fail_thrown);
   23180          75 :   CHECK(catch_callback_called);
   23181             : 
   23182          75 :   access_check_fail_thrown = false;
   23183          75 :   catch_callback_called = false;
   23184             :   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   23185          75 :   CHECK(!access_check_fail_thrown);
   23186          75 :   CHECK(!catch_callback_called);
   23187          75 : }
   23188             : 
   23189             : 
   23190       23723 : TEST(AccessCheckThrows) {
   23191           5 :   i::FLAG_allow_natives_syntax = true;
   23192           5 :   v8::V8::Initialize();
   23193           5 :   v8::Isolate* isolate = CcTest::isolate();
   23194           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   23195           5 :   v8::HandleScope scope(isolate);
   23196             : 
   23197             :   // Create an ObjectTemplate for global objects and install access
   23198             :   // check callbacks that will block access.
   23199             :   v8::Local<v8::ObjectTemplate> global_template =
   23200           5 :       v8::ObjectTemplate::New(isolate);
   23201           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   23202             : 
   23203             :   // Create a context and set an x property on it's global object.
   23204          10 :   LocalContext context0(nullptr, global_template);
   23205           5 :   v8::Local<v8::Object> global0 = context0->Global();
   23206          15 :   CHECK(global0->Set(context0.local(), v8_str("x"), global0).FromJust());
   23207             : 
   23208             :   // Create a context with a different security token so that the
   23209             :   // failed access check callback will be called on each access.
   23210          10 :   LocalContext context1(nullptr, global_template);
   23211          25 :   CHECK(context1->Global()
   23212             :             ->Set(context1.local(), v8_str("other"), global0)
   23213             :             .FromJust());
   23214             : 
   23215             :   v8::Local<v8::FunctionTemplate> catcher_fun =
   23216           5 :       v8::FunctionTemplate::New(isolate, CatcherCallback);
   23217          35 :   CHECK(context1->Global()
   23218             :             ->Set(context1.local(), v8_str("catcher"),
   23219             :                   catcher_fun->GetFunction(context1.local()).ToLocalChecked())
   23220             :             .FromJust());
   23221             : 
   23222             :   v8::Local<v8::FunctionTemplate> has_own_property_fun =
   23223           5 :       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   23224          35 :   CHECK(context1->Global()
   23225             :             ->Set(context1.local(), v8_str("has_own_property"),
   23226             :                   has_own_property_fun->GetFunction(context1.local())
   23227             :                       .ToLocalChecked())
   23228             :             .FromJust());
   23229             : 
   23230             :   {
   23231           5 :     v8::TryCatch try_catch(isolate);
   23232           5 :     access_check_fail_thrown = false;
   23233             :     CompileRun("other.x;");
   23234           5 :     CHECK(access_check_fail_thrown);
   23235           5 :     CHECK(try_catch.HasCaught());
   23236             :   }
   23237             : 
   23238           5 :   CheckCorrectThrow("other.x");
   23239           5 :   CheckCorrectThrow("other[1]");
   23240           5 :   CheckCorrectThrow("JSON.stringify(other)");
   23241           5 :   CheckCorrectThrow("has_own_property(other, 'x')");
   23242           5 :   CheckCorrectThrow("%GetProperty(other, 'x')");
   23243           5 :   CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
   23244           5 :   CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
   23245             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kSloppy) == 0);
   23246             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kStrict) == 1);
   23247           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");  // 0 == SLOPPY
   23248           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 1)");  // 1 == STRICT
   23249           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   23250           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 1)");
   23251           5 :   CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
   23252           5 :   CheckCorrectThrow("%HasProperty(other, 'x')");
   23253           5 :   CheckCorrectThrow("Object.prototype.propertyIsEnumerable(other, 'x')");
   23254             :   // PROPERTY_ATTRIBUTES_NONE = 0
   23255             :   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   23256           5 :                         "other, 'x', null, null, 1)");
   23257             : 
   23258             :   // Reset the failed access check callback so it does not influence
   23259             :   // the other tests.
   23260          10 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   23261           5 : }
   23262             : 
   23263       23718 : TEST(AccessCheckInIC) {
   23264           0 :   i::FLAG_native_code_counters = true;
   23265           0 :   i::FLAG_opt = false;
   23266             : 
   23267             :   v8::Isolate::CreateParams create_params;
   23268           0 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   23269           0 :   create_params.counter_lookup_callback = LookupCounter;
   23270           0 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   23271             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   23272             : 
   23273             :   {
   23274             :     v8::Isolate::Scope isolate_scope(isolate);
   23275           0 :     LocalContext env(isolate);
   23276           0 :     v8::HandleScope scope(isolate);
   23277             : 
   23278             :     // Enforce recompilation of IC stubs that access megamorphic stub cache
   23279             :     // to respect enabled native code counters and stub cache test flags.
   23280             :     RecompileICStubs(i_isolate);
   23281             : 
   23282             :     // Create an ObjectTemplate for global objects and install access
   23283             :     // check callbacks that will block access.
   23284             :     v8::Local<v8::ObjectTemplate> global_template =
   23285           0 :         v8::ObjectTemplate::New(isolate);
   23286           0 :     global_template->SetAccessCheckCallback(AccessCounter);
   23287             : 
   23288             :     // Create a context and set an x property on its global object.
   23289           0 :     LocalContext context0(isolate, nullptr, global_template);
   23290           0 :     v8::Local<v8::Object> global0 = context0->Global();
   23291           0 :     CHECK(global0->Set(context0.local(), v8_str("x"), global0).FromJust());
   23292             : 
   23293             :     // Create a context with a different security token so that the
   23294             :     // failed access check callback will be called on each access.
   23295           0 :     LocalContext context1(isolate, nullptr, global_template);
   23296           0 :     CHECK(context1->Global()
   23297             :               ->Set(context1.local(), v8_str("other"), global0)
   23298             :               .FromJust());
   23299             : 
   23300             :     // Set different security tokens.
   23301           0 :     Local<Value> token0 = v8_str("token0");
   23302           0 :     context0.local()->SetSecurityToken(token0);
   23303           0 :     context1.local()->SetSecurityToken(v8_str("token1"));
   23304             : 
   23305           0 :     int initial_probes = probes_counter;
   23306           0 :     int initial_misses = misses_counter;
   23307           0 :     int initial_updates = updates_counter;
   23308           0 :     access_count = 0;
   23309             : 
   23310             :     // Create megamorphic load ic with a handler for "global0.x" compiled for
   23311             :     // context0.
   23312             :     CompileRun(context0.local(),
   23313             :                "Number(1).__proto__.x = null;\n"
   23314             :                "String(1).__proto__.x = null;\n"
   23315             :                "function get0(o) { return o.x; };\n"
   23316             :                "get0({x:1});\n"      // premonomorphic
   23317             :                "get0({x:1,a:0});\n"  // monomorphic
   23318             :                "get0({x:1,b:0});\n"  // polymorphic
   23319             :                "get0('str');\n"
   23320             :                "get0(1.1);\n"
   23321             :                "get0(this);\n"  // megamorphic
   23322           0 :                "");
   23323           0 :     CHECK_EQ(0, probes_counter - initial_probes);
   23324           0 :     CHECK_EQ(0, misses_counter - initial_misses);
   23325           0 :     CHECK_EQ(5, updates_counter - initial_updates);
   23326             : 
   23327             :     // Create megamorphic load ic in context1.
   23328             :     CompileRun(context1.local(),
   23329             :                "function get1(o) { return o.x; };\n"
   23330             :                "get1({x:1});\n"      // premonomorphic
   23331             :                "get1({x:1,a:0});\n"  // monomorphic
   23332             :                "get1({x:1,b:0});\n"  // polymorphic
   23333             :                "get1({x:1,c:0});\n"
   23334             :                "get1({x:1,d:0});\n"
   23335             :                "get1({x:1,e:0});\n"  // megamorphic
   23336           0 :                "");
   23337           0 :     CHECK_EQ(0, access_count);
   23338           0 :     CHECK_EQ(0, probes_counter - initial_probes);
   23339           0 :     CHECK_EQ(0, misses_counter - initial_misses);
   23340           0 :     CHECK_EQ(10, updates_counter - initial_updates);
   23341             : 
   23342             :     // Feed the |other| to the load ic and ensure that it doesn't pick the
   23343             :     // handler for "global0.x" compiled for context0 from the megamorphic
   23344             :     // cache but create another handler for "global0.x" compiled for context1
   23345             :     // and ensure the access check callback is triggered.
   23346           0 :     CompileRun(context1.local(), "get1(other)");
   23347           0 :     CHECK_EQ(1, access_count);  // Access check callback must be triggered.
   23348             : 
   23349             :     // Feed the primitive objects to the load ic and ensure that it doesn't
   23350             :     // pick handlers for primitive maps from the megamorphic stub cache even
   23351             :     // if the security token matches.
   23352           0 :     context1.local()->SetSecurityToken(token0);
   23353           0 :     CHECK(CompileRun(context1.local(), "get1(1.1)")
   23354             :               .ToLocalChecked()
   23355             :               ->IsUndefined());
   23356           0 :     CHECK(CompileRun(context1.local(), "get1('str')")
   23357             :               .ToLocalChecked()
   23358             :               ->IsUndefined());
   23359             : 
   23360           0 :     CHECK_EQ(1, access_count);  // Access check callback must be triggered.
   23361           0 :     CHECK_EQ(3, probes_counter - initial_probes);
   23362           0 :     CHECK_EQ(0, misses_counter - initial_misses);
   23363           0 :     CHECK_EQ(13, updates_counter - initial_updates);
   23364             :   }
   23365           0 :   isolate->Dispose();
   23366           0 : }
   23367             : 
   23368             : class RequestInterruptTestBase {
   23369             :  public:
   23370          35 :   RequestInterruptTestBase()
   23371             :       : env_(),
   23372          35 :         isolate_(env_->GetIsolate()),
   23373             :         sem_(0),
   23374             :         warmup_(20000),
   23375         105 :         should_continue_(true) {
   23376          35 :   }
   23377             : 
   23378          35 :   virtual ~RequestInterruptTestBase() { }
   23379             : 
   23380             :   virtual void StartInterruptThread() = 0;
   23381             : 
   23382             :   virtual void TestBody() = 0;
   23383             : 
   23384          70 :   void RunTest() {
   23385          35 :     StartInterruptThread();
   23386             : 
   23387          35 :     v8::HandleScope handle_scope(isolate_);
   23388             : 
   23389          35 :     TestBody();
   23390             : 
   23391             :     // Verify we arrived here because interruptor was called
   23392             :     // not due to a bug causing us to exit the loop too early.
   23393          35 :     CHECK(!should_continue());
   23394          35 :   }
   23395             : 
   23396             :   void WakeUpInterruptor() {
   23397          35 :     sem_.Signal();
   23398             :   }
   23399             : 
   23400             :   bool should_continue() const { return should_continue_; }
   23401             : 
   23402     1707246 :   bool ShouldContinue() {
   23403     1707246 :     if (warmup_ > 0) {
   23404      600000 :       if (--warmup_ == 0) {
   23405             :         WakeUpInterruptor();
   23406             :       }
   23407             :     }
   23408             : 
   23409     1707246 :     return should_continue_;
   23410             :   }
   23411             : 
   23412     1208668 :   static void ShouldContinueCallback(
   23413     2417336 :       const v8::FunctionCallbackInfo<Value>& info) {
   23414             :     RequestInterruptTestBase* test =
   23415             :         reinterpret_cast<RequestInterruptTestBase*>(
   23416     1208668 :             info.Data().As<v8::External>()->Value());
   23417     1208668 :     info.GetReturnValue().Set(test->ShouldContinue());
   23418     1208668 :   }
   23419             : 
   23420             :   LocalContext env_;
   23421             :   v8::Isolate* isolate_;
   23422             :   v8::base::Semaphore sem_;
   23423             :   int warmup_;
   23424             :   bool should_continue_;
   23425             : };
   23426             : 
   23427             : 
   23428          60 : class RequestInterruptTestBaseWithSimpleInterrupt
   23429             :     : public RequestInterruptTestBase {
   23430             :  public:
   23431          60 :   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   23432             : 
   23433          30 :   virtual void StartInterruptThread() {
   23434          30 :     i_thread.Start();
   23435          30 :   }
   23436             : 
   23437             :  private:
   23438          30 :   class InterruptThread : public v8::base::Thread {
   23439             :    public:
   23440             :     explicit InterruptThread(RequestInterruptTestBase* test)
   23441          30 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   23442             : 
   23443          30 :     virtual void Run() {
   23444          30 :       test_->sem_.Wait();
   23445          30 :       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   23446          30 :     }
   23447             : 
   23448          30 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   23449             :       reinterpret_cast<RequestInterruptTestBase*>(data)->
   23450          30 :           should_continue_ = false;
   23451          30 :     }
   23452             : 
   23453             :    private:
   23454             :      RequestInterruptTestBase* test_;
   23455             :   };
   23456             : 
   23457             :   InterruptThread i_thread;
   23458             : };
   23459             : 
   23460             : 
   23461          10 : class RequestInterruptTestWithFunctionCall
   23462             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23463             :  public:
   23464           5 :   virtual void TestBody() {
   23465             :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23466          15 :                                          v8::External::New(isolate_, this))
   23467           5 :                                .ToLocalChecked();
   23468          25 :     CHECK(env_->Global()
   23469             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23470             :               .FromJust());
   23471             : 
   23472             :     CompileRun("while (ShouldContinue()) { }");
   23473           5 :   }
   23474             : };
   23475             : 
   23476             : 
   23477          10 : class RequestInterruptTestWithMethodCall
   23478             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23479             :  public:
   23480           5 :   virtual void TestBody() {
   23481           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23482           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23483             :     proto->Set(v8_str("shouldContinue"),
   23484             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23485          20 :                                      v8::External::New(isolate_, this)));
   23486          30 :     CHECK(env_->Global()
   23487             :               ->Set(env_.local(), v8_str("Klass"),
   23488             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23489             :               .FromJust());
   23490             : 
   23491             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23492           5 :   }
   23493             : };
   23494             : 
   23495             : 
   23496          10 : class RequestInterruptTestWithAccessor
   23497             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23498             :  public:
   23499           5 :   virtual void TestBody() {
   23500           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23501           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23502             :     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   23503          15 :         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   23504          30 :     CHECK(env_->Global()
   23505             :               ->Set(env_.local(), v8_str("Klass"),
   23506             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23507             :               .FromJust());
   23508             : 
   23509             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   23510           5 :   }
   23511             : };
   23512             : 
   23513             : 
   23514          10 : class RequestInterruptTestWithNativeAccessor
   23515             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23516             :  public:
   23517           5 :   virtual void TestBody() {
   23518           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23519          10 :     t->InstanceTemplate()->SetNativeDataProperty(
   23520             :         v8_str("shouldContinue"), &ShouldContinueNativeGetter, nullptr,
   23521          20 :         v8::External::New(isolate_, this));
   23522          30 :     CHECK(env_->Global()
   23523             :               ->Set(env_.local(), v8_str("Klass"),
   23524             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23525             :               .FromJust());
   23526             : 
   23527             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   23528           5 :   }
   23529             : 
   23530             :  private:
   23531      498578 :   static void ShouldContinueNativeGetter(
   23532             :       Local<String> property,
   23533             :       const v8::PropertyCallbackInfo<v8::Value>& info) {
   23534             :     RequestInterruptTestBase* test =
   23535             :         reinterpret_cast<RequestInterruptTestBase*>(
   23536      498578 :             info.Data().As<v8::External>()->Value());
   23537      498578 :     info.GetReturnValue().Set(test->ShouldContinue());
   23538      498578 :   }
   23539             : };
   23540             : 
   23541             : 
   23542          10 : class RequestInterruptTestWithMethodCallAndInterceptor
   23543             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23544             :  public:
   23545           5 :   virtual void TestBody() {
   23546           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23547           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23548             :     proto->Set(v8_str("shouldContinue"),
   23549             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23550          20 :                                      v8::External::New(isolate_, this)));
   23551           5 :     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   23552             :     instance_template->SetHandler(
   23553           5 :         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
   23554             : 
   23555          30 :     CHECK(env_->Global()
   23556             :               ->Set(env_.local(), v8_str("Klass"),
   23557             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23558             :               .FromJust());
   23559             : 
   23560             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23561           5 :   }
   23562             : 
   23563             :  private:
   23564      145401 :   static void EmptyInterceptor(
   23565      145401 :       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   23566             : };
   23567             : 
   23568             : 
   23569          10 : class RequestInterruptTestWithMathAbs
   23570             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23571             :  public:
   23572           5 :   virtual void TestBody() {
   23573             :     env_->Global()
   23574             :         ->Set(env_.local(), v8_str("WakeUpInterruptor"),
   23575             :               Function::New(env_.local(), WakeUpInterruptorCallback,
   23576          15 :                             v8::External::New(isolate_, this))
   23577          25 :                   .ToLocalChecked())
   23578          10 :         .FromJust();
   23579             : 
   23580             :     env_->Global()
   23581             :         ->Set(env_.local(), v8_str("ShouldContinue"),
   23582             :               Function::New(env_.local(), ShouldContinueCallback,
   23583          15 :                             v8::External::New(isolate_, this))
   23584          25 :                   .ToLocalChecked())
   23585          10 :         .FromJust();
   23586             : 
   23587           5 :     i::FLAG_allow_natives_syntax = true;
   23588             :     CompileRun("function loopish(o) {"
   23589             :                "  var pre = 10;"
   23590             :                "  while (o.abs(1) > 0) {"
   23591             :                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   23592             :                "    if (pre > 0) {"
   23593             :                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   23594             :                "    }"
   23595             :                "  }"
   23596             :                "}"
   23597             :                "var i = 50;"
   23598             :                "var obj = {abs: function () { return i-- }, x: null};"
   23599             :                "delete obj.x;"
   23600             :                "loopish(obj);"
   23601             :                "%OptimizeFunctionOnNextCall(loopish);"
   23602             :                "loopish(Math);");
   23603             : 
   23604           5 :     i::FLAG_allow_natives_syntax = false;
   23605           5 :   }
   23606             : 
   23607             :  private:
   23608          10 :   static void WakeUpInterruptorCallback(
   23609          15 :       const v8::FunctionCallbackInfo<Value>& info) {
   23610          10 :     if (!info[0]
   23611          10 :              ->BooleanValue(info.GetIsolate()->GetCurrentContext())
   23612          20 :              .FromJust()) {
   23613          10 :       return;
   23614             :     }
   23615             : 
   23616             :     RequestInterruptTestBase* test =
   23617             :         reinterpret_cast<RequestInterruptTestBase*>(
   23618           5 :             info.Data().As<v8::External>()->Value());
   23619             :     test->WakeUpInterruptor();
   23620             :   }
   23621             : 
   23622      140258 :   static void ShouldContinueCallback(
   23623      280516 :       const v8::FunctionCallbackInfo<Value>& info) {
   23624      140258 :     RequestInterruptTestBase* test =
   23625             :         reinterpret_cast<RequestInterruptTestBase*>(
   23626      140258 :             info.Data().As<v8::External>()->Value());
   23627             :     info.GetReturnValue().Set(test->should_continue());
   23628      140258 :   }
   23629             : };
   23630             : 
   23631             : 
   23632       23723 : TEST(RequestInterruptTestWithFunctionCall) {
   23633          15 :   RequestInterruptTestWithFunctionCall().RunTest();
   23634           5 : }
   23635             : 
   23636             : 
   23637       23723 : TEST(RequestInterruptTestWithMethodCall) {
   23638          15 :   RequestInterruptTestWithMethodCall().RunTest();
   23639           5 : }
   23640             : 
   23641             : 
   23642       23723 : TEST(RequestInterruptTestWithAccessor) {
   23643          15 :   RequestInterruptTestWithAccessor().RunTest();
   23644           5 : }
   23645             : 
   23646             : 
   23647       23723 : TEST(RequestInterruptTestWithNativeAccessor) {
   23648          15 :   RequestInterruptTestWithNativeAccessor().RunTest();
   23649           5 : }
   23650             : 
   23651             : 
   23652       23723 : TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   23653          15 :   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   23654           5 : }
   23655             : 
   23656             : 
   23657       23723 : TEST(RequestInterruptTestWithMathAbs) {
   23658          15 :   RequestInterruptTestWithMathAbs().RunTest();
   23659           5 : }
   23660             : 
   23661             : 
   23662          10 : class RequestMultipleInterrupts : public RequestInterruptTestBase {
   23663             :  public:
   23664          10 :   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
   23665             : 
   23666           5 :   virtual void StartInterruptThread() {
   23667           5 :     i_thread.Start();
   23668           5 :   }
   23669             : 
   23670           5 :   virtual void TestBody() {
   23671             :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23672          15 :                                          v8::External::New(isolate_, this))
   23673           5 :                                .ToLocalChecked();
   23674          25 :     CHECK(env_->Global()
   23675             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23676             :               .FromJust());
   23677             : 
   23678             :     CompileRun("while (ShouldContinue()) { }");
   23679           5 :   }
   23680             : 
   23681             :  private:
   23682           5 :   class InterruptThread : public v8::base::Thread {
   23683             :    public:
   23684             :     enum { NUM_INTERRUPTS = 10 };
   23685             :     explicit InterruptThread(RequestMultipleInterrupts* test)
   23686           5 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   23687             : 
   23688           5 :     virtual void Run() {
   23689           5 :       test_->sem_.Wait();
   23690          55 :       for (int i = 0; i < NUM_INTERRUPTS; i++) {
   23691          50 :         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   23692             :       }
   23693           5 :     }
   23694             : 
   23695          50 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   23696             :       RequestMultipleInterrupts* test =
   23697             :           reinterpret_cast<RequestMultipleInterrupts*>(data);
   23698          50 :       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
   23699          50 :     }
   23700             : 
   23701             :    private:
   23702             :     RequestMultipleInterrupts* test_;
   23703             :   };
   23704             : 
   23705             :   InterruptThread i_thread;
   23706             :   int counter_;
   23707             : };
   23708             : 
   23709             : 
   23710       23723 : TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
   23711             : 
   23712             : 
   23713             : static bool interrupt_was_called = false;
   23714             : 
   23715             : 
   23716           5 : void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
   23717           5 :   interrupt_was_called = true;
   23718           5 : }
   23719             : 
   23720             : 
   23721       23723 : TEST(RequestInterruptSmallScripts) {
   23722           5 :   LocalContext env;
   23723           5 :   v8::Isolate* isolate = CcTest::isolate();
   23724          10 :   v8::HandleScope scope(isolate);
   23725             : 
   23726           5 :   interrupt_was_called = false;
   23727           5 :   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, nullptr);
   23728             :   CompileRun("(function(x){return x;})(1);");
   23729          10 :   CHECK(interrupt_was_called);
   23730           5 : }
   23731             : 
   23732             : 
   23733             : static Local<Value> function_new_expected_env;
   23734          24 : static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   23735          36 :   CHECK(
   23736             :       function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
   23737             :                                         info.Data())
   23738             :           .FromJust());
   23739             :   info.GetReturnValue().Set(17);
   23740          12 : }
   23741             : 
   23742             : 
   23743       23724 : THREADED_TEST(FunctionNew) {
   23744           6 :   LocalContext env;
   23745           6 :   v8::Isolate* isolate = env->GetIsolate();
   23746          12 :   v8::HandleScope scope(isolate);
   23747           6 :   Local<Object> data = v8::Object::New(isolate);
   23748           6 :   function_new_expected_env = data;
   23749             :   Local<Function> func =
   23750          12 :       Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
   23751          30 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   23752           6 :   Local<Value> result = CompileRun("func();");
   23753          18 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
   23754             :   // Serial number should be invalid => should not be cached.
   23755             :   auto serial_number =
   23756             :       i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
   23757             :                        ->shared()
   23758             :                        ->get_api_func_data()
   23759             :                        ->serial_number())
   23760             :           ->value();
   23761           6 :   CHECK_EQ(i::FunctionTemplateInfo::kInvalidSerialNumber, serial_number);
   23762             : 
   23763             :   // Verify that each Function::New creates a new function instance
   23764           6 :   Local<Object> data2 = v8::Object::New(isolate);
   23765           6 :   function_new_expected_env = data2;
   23766             :   Local<Function> func2 =
   23767          12 :       Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
   23768           6 :   CHECK(!func2->IsNull());
   23769          12 :   CHECK(!func->Equals(env.local(), func2).FromJust());
   23770          30 :   CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   23771           6 :   Local<Value> result2 = CompileRun("func2();");
   23772          24 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
   23773           6 : }
   23774             : 
   23775             : 
   23776       23723 : TEST(EscapeableHandleScope) {
   23777           5 :   HandleScope outer_scope(CcTest::isolate());
   23778          10 :   LocalContext context;
   23779             :   const int runs = 10;
   23780          55 :   Local<String> values[runs];
   23781          50 :   for (int i = 0; i < runs; i++) {
   23782          50 :     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   23783             :     Local<String> value;
   23784          50 :     if (i != 0) value = v8_str("escape value");
   23785          50 :     values[i] = inner_scope.Escape(value);
   23786             :   }
   23787          50 :   for (int i = 0; i < runs; i++) {
   23788             :     Local<String> expected;
   23789          50 :     if (i != 0) {
   23790         135 :       CHECK(v8_str("escape value")
   23791             :                 ->Equals(context.local(), values[i])
   23792             :                 .FromJust());
   23793             :     } else {
   23794          10 :       CHECK(values[i].IsEmpty());
   23795             :     }
   23796           5 :   }
   23797           5 : }
   23798             : 
   23799             : 
   23800          20 : static void SetterWhichExpectsThisAndHolderToDiffer(
   23801             :     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   23802          20 :   CHECK(info.Holder() != info.This());
   23803          20 : }
   23804             : 
   23805             : 
   23806       23723 : TEST(Regress239669) {
   23807           5 :   LocalContext context;
   23808           5 :   v8::Isolate* isolate = context->GetIsolate();
   23809          10 :   v8::HandleScope scope(isolate);
   23810           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   23811           5 :   templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
   23812          30 :   CHECK(context->Global()
   23813             :             ->Set(context.local(), v8_str("P"),
   23814             :                   templ->NewInstance(context.local()).ToLocalChecked())
   23815             :             .FromJust());
   23816             :   CompileRun(
   23817             :       "function C1() {"
   23818             :       "  this.x = 23;"
   23819             :       "};"
   23820             :       "C1.prototype = P;"
   23821             :       "for (var i = 0; i < 4; i++ ) {"
   23822             :       "  new C1();"
   23823           5 :       "}");
   23824           5 : }
   23825             : 
   23826             : 
   23827             : class ApiCallOptimizationChecker {
   23828             :  private:
   23829             :   static Local<Object> data;
   23830             :   static Local<Object> receiver;
   23831             :   static Local<Object> holder;
   23832             :   static Local<Object> callee;
   23833             :   static int count;
   23834             : 
   23835         270 :   static void OptimizationCallback(
   23836        1350 :       const v8::FunctionCallbackInfo<v8::Value>& info) {
   23837         270 :     CHECK(data == info.Data());
   23838         270 :     CHECK(receiver == info.This());
   23839         270 :     if (info.Length() == 1) {
   23840         270 :       CHECK(v8_num(1)
   23841             :                 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
   23842             :                 .FromJust());
   23843             :     }
   23844         270 :     CHECK(holder == info.Holder());
   23845         270 :     count++;
   23846         270 :     info.GetReturnValue().Set(v8_str("returned"));
   23847         270 :   }
   23848             : 
   23849             :  public:
   23850             :   enum SignatureType {
   23851             :     kNoSignature,
   23852             :     kSignatureOnReceiver,
   23853             :     kSignatureOnPrototype
   23854             :   };
   23855             : 
   23856           5 :   void RunAll() {
   23857             :     SignatureType signature_types[] =
   23858           5 :       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   23859          20 :     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   23860          15 :       SignatureType signature_type = signature_types[i];
   23861          45 :       for (int j = 0; j < 2; j++) {
   23862          30 :         bool global = j == 0;
   23863             :         int key = signature_type +
   23864          30 :             arraysize(signature_types) * (global ? 1 : 0);
   23865          30 :         Run(signature_type, global, key);
   23866             :       }
   23867             :     }
   23868           5 :   }
   23869             : 
   23870          30 :   void Run(SignatureType signature_type, bool global, int key) {
   23871          30 :     v8::Isolate* isolate = CcTest::isolate();
   23872          30 :     v8::HandleScope scope(isolate);
   23873             :     // Build a template for signature checks.
   23874             :     Local<v8::ObjectTemplate> signature_template;
   23875             :     Local<v8::Signature> signature;
   23876             :     {
   23877             :       Local<v8::FunctionTemplate> parent_template =
   23878          30 :         FunctionTemplate::New(isolate);
   23879          30 :       parent_template->SetHiddenPrototype(true);
   23880             :       Local<v8::FunctionTemplate> function_template
   23881          30 :           = FunctionTemplate::New(isolate);
   23882          30 :       function_template->Inherit(parent_template);
   23883          30 :       switch (signature_type) {
   23884             :         case kNoSignature:
   23885             :           break;
   23886             :         case kSignatureOnReceiver:
   23887          10 :           signature = v8::Signature::New(isolate, function_template);
   23888          10 :           break;
   23889             :         case kSignatureOnPrototype:
   23890          10 :           signature = v8::Signature::New(isolate, parent_template);
   23891          10 :           break;
   23892             :       }
   23893          30 :       signature_template = function_template->InstanceTemplate();
   23894             :     }
   23895             :     // Global object must pass checks.
   23896             :     Local<v8::Context> context =
   23897          30 :         v8::Context::New(isolate, nullptr, signature_template);
   23898             :     v8::Context::Scope context_scope(context);
   23899             :     // Install regular object that can pass signature checks.
   23900             :     Local<Object> function_receiver =
   23901          30 :         signature_template->NewInstance(context).ToLocalChecked();
   23902         120 :     CHECK(context->Global()
   23903             :               ->Set(context, v8_str("function_receiver"), function_receiver)
   23904             :               .FromJust());
   23905             :     // Get the holder objects.
   23906             :     Local<Object> inner_global =
   23907          60 :         Local<Object>::Cast(context->Global()->GetPrototype());
   23908             :     // Install functions on hidden prototype object if there is one.
   23909          30 :     data = Object::New(isolate);
   23910             :     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   23911          30 :         isolate, OptimizationCallback, data, signature);
   23912             :     Local<Function> function =
   23913          30 :         function_template->GetFunction(context).ToLocalChecked();
   23914             :     Local<Object> global_holder = inner_global;
   23915             :     Local<Object> function_holder = function_receiver;
   23916          30 :     if (signature_type == kSignatureOnPrototype) {
   23917          10 :       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   23918          10 :       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   23919             :     }
   23920          90 :     global_holder->Set(context, v8_str("g_f"), function).FromJust();
   23921          60 :     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   23922          90 :     function_holder->Set(context, v8_str("f"), function).FromJust();
   23923          60 :     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   23924             :     // Initialize expected values.
   23925          30 :     callee = function;
   23926          30 :     count = 0;
   23927          30 :     if (global) {
   23928          15 :       receiver = context->Global();
   23929          15 :       holder = inner_global;
   23930             :     } else {
   23931          15 :       holder = function_receiver;
   23932             :       // If not using a signature, add something else to the prototype chain
   23933             :       // to test the case that holder != receiver
   23934          15 :       if (signature_type == kNoSignature) {
   23935             :         receiver = Local<Object>::Cast(CompileRun(
   23936             :             "var receiver_subclass = {};\n"
   23937             :             "receiver_subclass.__proto__ = function_receiver;\n"
   23938           5 :             "receiver_subclass"));
   23939             :       } else {
   23940             :         receiver = Local<Object>::Cast(CompileRun(
   23941             :           "var receiver_subclass = function_receiver;\n"
   23942          10 :           "receiver_subclass"));
   23943             :       }
   23944             :     }
   23945             :     // With no signature, the holder is not set.
   23946          30 :     if (signature_type == kNoSignature) holder = receiver;
   23947             :     // build wrap_function
   23948             :     i::ScopedVector<char> wrap_function(200);
   23949          30 :     if (global) {
   23950             :       i::SNPrintF(
   23951             :           wrap_function,
   23952             :           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   23953             :           "function wrap_get_%d() { return this.g_acc; }\n"
   23954             :           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   23955          15 :           key, key, key);
   23956             :     } else {
   23957             :       i::SNPrintF(
   23958             :           wrap_function,
   23959             :           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   23960             :           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   23961             :           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   23962          15 :           key, key, key);
   23963             :     }
   23964             :     // build source string
   23965             :     i::ScopedVector<char> source(1000);
   23966             :     i::SNPrintF(
   23967             :         source,
   23968             :         "%s\n"  // wrap functions
   23969             :         "function wrap_f() { return wrap_f_%d(); }\n"
   23970             :         "function wrap_get() { return wrap_get_%d(); }\n"
   23971             :         "function wrap_set() { return wrap_set_%d(); }\n"
   23972             :         "check = function(returned) {\n"
   23973             :         "  if (returned !== 'returned') { throw returned; }\n"
   23974             :         "}\n"
   23975             :         "\n"
   23976             :         "check(wrap_f());\n"
   23977             :         "check(wrap_f());\n"
   23978             :         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   23979             :         "check(wrap_f());\n"
   23980             :         "\n"
   23981             :         "check(wrap_get());\n"
   23982             :         "check(wrap_get());\n"
   23983             :         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   23984             :         "check(wrap_get());\n"
   23985             :         "\n"
   23986             :         "check = function(returned) {\n"
   23987             :         "  if (returned !== 1) { throw returned; }\n"
   23988             :         "}\n"
   23989             :         "check(wrap_set());\n"
   23990             :         "check(wrap_set());\n"
   23991             :         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   23992             :         "check(wrap_set());\n",
   23993          30 :         wrap_function.start(), key, key, key, key, key, key);
   23994          60 :     v8::TryCatch try_catch(isolate);
   23995             :     CompileRun(source.start());
   23996          30 :     CHECK(!try_catch.HasCaught());
   23997          60 :     CHECK_EQ(9, count);
   23998          30 :   }
   23999             : };
   24000             : 
   24001             : 
   24002             : Local<Object> ApiCallOptimizationChecker::data;
   24003             : Local<Object> ApiCallOptimizationChecker::receiver;
   24004             : Local<Object> ApiCallOptimizationChecker::holder;
   24005             : Local<Object> ApiCallOptimizationChecker::callee;
   24006             : int ApiCallOptimizationChecker::count = 0;
   24007             : 
   24008             : 
   24009       23723 : TEST(FunctionCallOptimization) {
   24010           5 :   i::FLAG_allow_natives_syntax = true;
   24011             :   ApiCallOptimizationChecker checker;
   24012           5 :   checker.RunAll();
   24013           5 : }
   24014             : 
   24015             : 
   24016       23723 : TEST(FunctionCallOptimizationMultipleArgs) {
   24017           5 :   i::FLAG_allow_natives_syntax = true;
   24018           5 :   LocalContext context;
   24019           5 :   v8::Isolate* isolate = context->GetIsolate();
   24020          10 :   v8::HandleScope scope(isolate);
   24021           5 :   Local<Object> global = context->Global();
   24022             :   Local<v8::Function> function =
   24023          10 :       Function::New(context.local(), Returns42).ToLocalChecked();
   24024          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   24025             :   CompileRun(
   24026             :       "function x_wrap() {\n"
   24027             :       "  for (var i = 0; i < 5; i++) {\n"
   24028             :       "    x(1,2,3);\n"
   24029             :       "  }\n"
   24030             :       "}\n"
   24031             :       "x_wrap();\n"
   24032             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   24033           5 :       "x_wrap();\n");
   24034           5 : }
   24035             : 
   24036             : 
   24037          50 : static void ReturnsSymbolCallback(
   24038         100 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   24039         100 :   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
   24040          50 : }
   24041             : 
   24042             : 
   24043       23723 : TEST(ApiCallbackCanReturnSymbols) {
   24044           5 :   i::FLAG_allow_natives_syntax = true;
   24045           5 :   LocalContext context;
   24046           5 :   v8::Isolate* isolate = context->GetIsolate();
   24047          10 :   v8::HandleScope scope(isolate);
   24048           5 :   Local<Object> global = context->Global();
   24049             :   Local<v8::Function> function =
   24050          10 :       Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
   24051          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   24052             :   CompileRun(
   24053             :       "function x_wrap() {\n"
   24054             :       "  for (var i = 0; i < 5; i++) {\n"
   24055             :       "    x();\n"
   24056             :       "  }\n"
   24057             :       "}\n"
   24058             :       "x_wrap();\n"
   24059             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   24060           5 :       "x_wrap();\n");
   24061           5 : }
   24062             : 
   24063             : 
   24064       23723 : TEST(EmptyApiCallback) {
   24065           5 :   LocalContext context;
   24066           5 :   auto isolate = context->GetIsolate();
   24067          10 :   v8::HandleScope scope(isolate);
   24068           5 :   auto global = context->Global();
   24069           5 :   auto function = FunctionTemplate::New(isolate)
   24070          15 :                       ->GetFunction(context.local())
   24071           5 :                       .ToLocalChecked();
   24072          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   24073             : 
   24074             :   auto result = CompileRun("x()");
   24075           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24076             : 
   24077             :   result = CompileRun("x(1,2,3)");
   24078           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24079             : 
   24080             :   result = CompileRun("x.call(undefined)");
   24081           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24082             : 
   24083             :   result = CompileRun("x.call(null)");
   24084           5 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24085             : 
   24086             :   result = CompileRun("7 + x.call(3) + 11");
   24087           5 :   CHECK(result->IsInt32());
   24088          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   24089             : 
   24090             :   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
   24091           5 :   CHECK(result->IsInt32());
   24092          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   24093             : 
   24094             :   result = CompileRun("var y = []; x.call(y)");
   24095           5 :   CHECK(result->IsArray());
   24096             : 
   24097             :   result = CompileRun("x.call(y, 1, 2, 3, 4)");
   24098          10 :   CHECK(result->IsArray());
   24099           5 : }
   24100             : 
   24101             : 
   24102       23723 : TEST(SimpleSignatureCheck) {
   24103           5 :   LocalContext context;
   24104           5 :   auto isolate = context->GetIsolate();
   24105          10 :   v8::HandleScope scope(isolate);
   24106           5 :   auto global = context->Global();
   24107           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   24108           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   24109           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   24110             :   global->Set(context.local(), v8_str("sig_obj"),
   24111          25 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   24112          10 :       .FromJust();
   24113             :   global->Set(context.local(), v8_str("x"),
   24114          25 :               x->GetFunction(context.local()).ToLocalChecked())
   24115          10 :       .FromJust();
   24116             :   CompileRun("var s = new sig_obj();");
   24117             :   {
   24118           5 :     TryCatch try_catch(isolate);
   24119             :     CompileRun("x()");
   24120           5 :     CHECK(try_catch.HasCaught());
   24121             :   }
   24122             :   {
   24123           5 :     TryCatch try_catch(isolate);
   24124             :     CompileRun("x.call(1)");
   24125           5 :     CHECK(try_catch.HasCaught());
   24126             :   }
   24127             :   {
   24128           5 :     TryCatch try_catch(isolate);
   24129             :     auto result = CompileRun("s.x = x; s.x()");
   24130           5 :     CHECK(!try_catch.HasCaught());
   24131          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24132             :   }
   24133             :   {
   24134           5 :     TryCatch try_catch(isolate);
   24135             :     auto result = CompileRun("x.call(s)");
   24136           5 :     CHECK(!try_catch.HasCaught());
   24137          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24138           5 :   }
   24139           5 : }
   24140             : 
   24141             : 
   24142       23723 : TEST(ChainSignatureCheck) {
   24143           5 :   LocalContext context;
   24144           5 :   auto isolate = context->GetIsolate();
   24145          10 :   v8::HandleScope scope(isolate);
   24146           5 :   auto global = context->Global();
   24147           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   24148           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   24149          25 :   for (int i = 0; i < 4; ++i) {
   24150          20 :     auto temp = FunctionTemplate::New(isolate);
   24151          20 :     temp->Inherit(sig_obj);
   24152             :     sig_obj = temp;
   24153             :   }
   24154           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   24155             :   global->Set(context.local(), v8_str("sig_obj"),
   24156          20 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   24157          10 :       .FromJust();
   24158             :   global->Set(context.local(), v8_str("x"),
   24159          25 :               x->GetFunction(context.local()).ToLocalChecked())
   24160          10 :       .FromJust();
   24161             :   CompileRun("var s = new sig_obj();");
   24162             :   {
   24163           5 :     TryCatch try_catch(isolate);
   24164             :     CompileRun("x()");
   24165           5 :     CHECK(try_catch.HasCaught());
   24166             :   }
   24167             :   {
   24168           5 :     TryCatch try_catch(isolate);
   24169             :     CompileRun("x.call(1)");
   24170           5 :     CHECK(try_catch.HasCaught());
   24171             :   }
   24172             :   {
   24173           5 :     TryCatch try_catch(isolate);
   24174             :     auto result = CompileRun("s.x = x; s.x()");
   24175           5 :     CHECK(!try_catch.HasCaught());
   24176          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24177             :   }
   24178             :   {
   24179           5 :     TryCatch try_catch(isolate);
   24180             :     auto result = CompileRun("x.call(s)");
   24181           5 :     CHECK(!try_catch.HasCaught());
   24182          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24183           5 :   }
   24184           5 : }
   24185             : 
   24186             : 
   24187       23723 : TEST(PrototypeSignatureCheck) {
   24188           5 :   LocalContext context;
   24189           5 :   auto isolate = context->GetIsolate();
   24190          10 :   v8::HandleScope scope(isolate);
   24191           5 :   auto global = context->Global();
   24192           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   24193           5 :   sig_obj->SetHiddenPrototype(true);
   24194           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   24195           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   24196             :   global->Set(context.local(), v8_str("sig_obj"),
   24197          20 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   24198          10 :       .FromJust();
   24199             :   global->Set(context.local(), v8_str("x"),
   24200          25 :               x->GetFunction(context.local()).ToLocalChecked())
   24201          10 :       .FromJust();
   24202             :   CompileRun("s = {}; s.__proto__ = new sig_obj();");
   24203             :   {
   24204           5 :     TryCatch try_catch(isolate);
   24205             :     CompileRun("x()");
   24206           5 :     CHECK(try_catch.HasCaught());
   24207             :   }
   24208             :   {
   24209           5 :     TryCatch try_catch(isolate);
   24210             :     CompileRun("x.call(1)");
   24211           5 :     CHECK(try_catch.HasCaught());
   24212             :   }
   24213             :   {
   24214           5 :     TryCatch try_catch(isolate);
   24215             :     auto result = CompileRun("s.x = x; s.x()");
   24216           5 :     CHECK(!try_catch.HasCaught());
   24217          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24218             :   }
   24219             :   {
   24220           5 :     TryCatch try_catch(isolate);
   24221             :     auto result = CompileRun("x.call(s)");
   24222           5 :     CHECK(!try_catch.HasCaught());
   24223          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24224           5 :   }
   24225           5 : }
   24226             : 
   24227             : 
   24228             : static const char* last_event_message;
   24229             : static int last_event_status;
   24230          10 : void StoringEventLoggerCallback(const char* message, int status) {
   24231          10 :     last_event_message = message;
   24232          10 :     last_event_status = status;
   24233          10 : }
   24234             : 
   24235             : 
   24236       23723 : TEST(EventLogging) {
   24237           5 :   v8::Isolate* isolate = CcTest::isolate();
   24238           5 :   isolate->SetEventLogger(StoringEventLoggerCallback);
   24239             :   v8::internal::HistogramTimer histogramTimer(
   24240             :       "V8.Test", 0, 10000, v8::internal::HistogramTimerResolution::MILLISECOND,
   24241             :       50, reinterpret_cast<v8::internal::Isolate*>(isolate)->counters());
   24242             :   histogramTimer.Start();
   24243           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   24244           5 :   CHECK_EQ(0, last_event_status);
   24245             :   histogramTimer.Stop();
   24246           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   24247           5 :   CHECK_EQ(1, last_event_status);
   24248           5 : }
   24249             : 
   24250       23723 : TEST(PropertyDescriptor) {
   24251           5 :   LocalContext context;
   24252           5 :   v8::Isolate* isolate = context->GetIsolate();
   24253          10 :   v8::HandleScope scope(isolate);
   24254             : 
   24255             :   {  // empty descriptor
   24256           5 :     v8::PropertyDescriptor desc;
   24257           5 :     CHECK(!desc.has_value());
   24258           5 :     CHECK(!desc.has_set());
   24259           5 :     CHECK(!desc.has_get());
   24260           5 :     CHECK(!desc.has_enumerable());
   24261           5 :     CHECK(!desc.has_configurable());
   24262           5 :     CHECK(!desc.has_writable());
   24263             :   }
   24264             :   {
   24265             :     // data descriptor
   24266           5 :     v8::PropertyDescriptor desc(v8_num(42));
   24267           5 :     desc.set_enumerable(false);
   24268          10 :     CHECK(desc.value() == v8_num(42));
   24269           5 :     CHECK(desc.has_value());
   24270           5 :     CHECK(!desc.has_set());
   24271           5 :     CHECK(!desc.has_get());
   24272           5 :     CHECK(desc.has_enumerable());
   24273           5 :     CHECK(!desc.enumerable());
   24274           5 :     CHECK(!desc.has_configurable());
   24275           5 :     CHECK(!desc.has_writable());
   24276             :   }
   24277             :   {
   24278             :     // data descriptor
   24279           5 :     v8::PropertyDescriptor desc(v8_num(42));
   24280           5 :     desc.set_configurable(true);
   24281          10 :     CHECK(desc.value() == v8_num(42));
   24282           5 :     CHECK(desc.has_value());
   24283           5 :     CHECK(!desc.has_set());
   24284           5 :     CHECK(!desc.has_get());
   24285           5 :     CHECK(desc.has_configurable());
   24286           5 :     CHECK(desc.configurable());
   24287           5 :     CHECK(!desc.has_enumerable());
   24288           5 :     CHECK(!desc.has_writable());
   24289             :   }
   24290             :   {
   24291             :     // data descriptor
   24292           5 :     v8::PropertyDescriptor desc(v8_num(42));
   24293           5 :     desc.set_configurable(false);
   24294          10 :     CHECK(desc.value() == v8_num(42));
   24295           5 :     CHECK(desc.has_value());
   24296           5 :     CHECK(!desc.has_set());
   24297           5 :     CHECK(!desc.has_get());
   24298           5 :     CHECK(desc.has_configurable());
   24299           5 :     CHECK(!desc.configurable());
   24300           5 :     CHECK(!desc.has_enumerable());
   24301           5 :     CHECK(!desc.has_writable());
   24302             :   }
   24303             :   {
   24304             :     // data descriptor
   24305           5 :     v8::PropertyDescriptor desc(v8_num(42), false);
   24306          10 :     CHECK(desc.value() == v8_num(42));
   24307           5 :     CHECK(desc.has_value());
   24308           5 :     CHECK(!desc.has_set());
   24309           5 :     CHECK(!desc.has_get());
   24310           5 :     CHECK(!desc.has_enumerable());
   24311           5 :     CHECK(!desc.has_configurable());
   24312           5 :     CHECK(desc.has_writable());
   24313           5 :     CHECK(!desc.writable());
   24314             :   }
   24315             :   {
   24316             :     // data descriptor
   24317           5 :     v8::PropertyDescriptor desc(v8::Local<v8::Value>(), true);
   24318           5 :     CHECK(!desc.has_value());
   24319           5 :     CHECK(!desc.has_set());
   24320           5 :     CHECK(!desc.has_get());
   24321           5 :     CHECK(!desc.has_enumerable());
   24322           5 :     CHECK(!desc.has_configurable());
   24323           5 :     CHECK(desc.has_writable());
   24324           5 :     CHECK(desc.writable());
   24325             :   }
   24326             :   {
   24327             :     // accessor descriptor
   24328             :     CompileRun("var set = function() {return 43;};");
   24329             : 
   24330             :     v8::Local<v8::Function> set =
   24331             :         v8::Local<v8::Function>::Cast(context->Global()
   24332          20 :                                           ->Get(context.local(), v8_str("set"))
   24333           5 :                                           .ToLocalChecked());
   24334           5 :     v8::PropertyDescriptor desc(v8::Undefined(isolate), set);
   24335           5 :     desc.set_configurable(false);
   24336           5 :     CHECK(!desc.has_value());
   24337           5 :     CHECK(desc.has_get());
   24338          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   24339           5 :     CHECK(desc.has_set());
   24340          10 :     CHECK(desc.set() == set);
   24341           5 :     CHECK(!desc.has_enumerable());
   24342           5 :     CHECK(desc.has_configurable());
   24343           5 :     CHECK(!desc.configurable());
   24344           5 :     CHECK(!desc.has_writable());
   24345             :   }
   24346             :   {
   24347             :     // accessor descriptor with Proxy
   24348             :     CompileRun(
   24349             :         "var set = new Proxy(function() {}, {});"
   24350             :         "var get = undefined;");
   24351             : 
   24352             :     v8::Local<v8::Value> get =
   24353             :         v8::Local<v8::Value>::Cast(context->Global()
   24354          20 :                                        ->Get(context.local(), v8_str("get"))
   24355          10 :                                        .ToLocalChecked());
   24356             :     v8::Local<v8::Function> set =
   24357             :         v8::Local<v8::Function>::Cast(context->Global()
   24358          20 :                                           ->Get(context.local(), v8_str("set"))
   24359           5 :                                           .ToLocalChecked());
   24360           5 :     v8::PropertyDescriptor desc(get, set);
   24361           5 :     desc.set_configurable(false);
   24362           5 :     CHECK(!desc.has_value());
   24363          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   24364           5 :     CHECK(desc.has_get());
   24365          10 :     CHECK(desc.set() == set);
   24366           5 :     CHECK(desc.has_set());
   24367           5 :     CHECK(!desc.has_enumerable());
   24368           5 :     CHECK(desc.has_configurable());
   24369           5 :     CHECK(!desc.configurable());
   24370           5 :     CHECK(!desc.has_writable());
   24371             :   }
   24372             :   {
   24373             :     // accessor descriptor with empty function handle
   24374             :     v8::Local<v8::Function> get = v8::Local<v8::Function>();
   24375           5 :     v8::PropertyDescriptor desc(get, get);
   24376           5 :     CHECK(!desc.has_value());
   24377           5 :     CHECK(!desc.has_get());
   24378           5 :     CHECK(!desc.has_set());
   24379           5 :     CHECK(!desc.has_enumerable());
   24380           5 :     CHECK(!desc.has_configurable());
   24381           5 :     CHECK(!desc.has_writable());
   24382           5 :   }
   24383           5 : }
   24384             : 
   24385       23723 : TEST(Promises) {
   24386           5 :   LocalContext context;
   24387           5 :   v8::Isolate* isolate = context->GetIsolate();
   24388          10 :   v8::HandleScope scope(isolate);
   24389             : 
   24390             :   // Creation.
   24391             :   Local<v8::Promise::Resolver> pr =
   24392           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24393             :   Local<v8::Promise::Resolver> rr =
   24394           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24395           5 :   Local<v8::Promise> p = pr->GetPromise();
   24396           5 :   Local<v8::Promise> r = rr->GetPromise();
   24397             : 
   24398             :   // IsPromise predicate.
   24399           5 :   CHECK(p->IsPromise());
   24400           5 :   CHECK(r->IsPromise());
   24401           5 :   Local<Value> o = v8::Object::New(isolate);
   24402           5 :   CHECK(!o->IsPromise());
   24403             : 
   24404             :   // Resolution and rejection.
   24405          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24406           5 :   CHECK(p->IsPromise());
   24407          15 :   rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
   24408          10 :   CHECK(r->IsPromise());
   24409           5 : }
   24410             : 
   24411             : 
   24412       23723 : TEST(PromiseThen) {
   24413           5 :   LocalContext context;
   24414           5 :   v8::Isolate* isolate = context->GetIsolate();
   24415           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   24416          10 :   v8::HandleScope scope(isolate);
   24417           5 :   Local<Object> global = context->Global();
   24418             : 
   24419             :   // Creation.
   24420             :   Local<v8::Promise::Resolver> pr =
   24421           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24422             :   Local<v8::Promise::Resolver> qr =
   24423           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24424           5 :   Local<v8::Promise> p = pr->GetPromise();
   24425           5 :   Local<v8::Promise> q = qr->GetPromise();
   24426             : 
   24427           5 :   CHECK(p->IsPromise());
   24428           5 :   CHECK(q->IsPromise());
   24429             : 
   24430          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24431          10 :   qr->Resolve(context.local(), p).FromJust();
   24432             : 
   24433             :   // Chaining non-pending promises.
   24434             :   CompileRun(
   24435             :       "var x1 = 0;\n"
   24436             :       "var x2 = 0;\n"
   24437             :       "function f1(x) { x1 = x; return x+1 };\n"
   24438             :       "function f2(x) { x2 = x; return x+1 };\n");
   24439             :   Local<Function> f1 = Local<Function>::Cast(
   24440          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   24441             :   Local<Function> f2 = Local<Function>::Cast(
   24442          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   24443             : 
   24444             :   // Then
   24445             :   CompileRun("x1 = x2 = 0;");
   24446           5 :   q->Then(context.local(), f1).ToLocalChecked();
   24447          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24448             :                   .ToLocalChecked()
   24449             :                   ->Int32Value(context.local())
   24450             :                   .FromJust());
   24451           5 :   isolate->RunMicrotasks();
   24452          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24453             :                   .ToLocalChecked()
   24454             :                   ->Int32Value(context.local())
   24455             :                   .FromJust());
   24456             : 
   24457             :   // Then
   24458             :   CompileRun("x1 = x2 = 0;");
   24459           5 :   pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24460           5 :   qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24461             : 
   24462          10 :   qr->Resolve(context.local(), pr).FromJust();
   24463             :   qr->GetPromise()
   24464          10 :       ->Then(context.local(), f1)
   24465           5 :       .ToLocalChecked()
   24466           5 :       ->Then(context.local(), f2)
   24467           5 :       .ToLocalChecked();
   24468             : 
   24469          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24470             :                   .ToLocalChecked()
   24471             :                   ->Int32Value(context.local())
   24472             :                   .FromJust());
   24473          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24474             :                   .ToLocalChecked()
   24475             :                   ->Int32Value(context.local())
   24476             :                   .FromJust());
   24477           5 :   isolate->RunMicrotasks();
   24478          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24479             :                   .ToLocalChecked()
   24480             :                   ->Int32Value(context.local())
   24481             :                   .FromJust());
   24482          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24483             :                   .ToLocalChecked()
   24484             :                   ->Int32Value(context.local())
   24485             :                   .FromJust());
   24486             : 
   24487          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
   24488             : 
   24489          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24490             :                   .ToLocalChecked()
   24491             :                   ->Int32Value(context.local())
   24492             :                   .FromJust());
   24493          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24494             :                   .ToLocalChecked()
   24495             :                   ->Int32Value(context.local())
   24496             :                   .FromJust());
   24497           5 :   isolate->RunMicrotasks();
   24498          20 :   CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
   24499             :                   .ToLocalChecked()
   24500             :                   ->Int32Value(context.local())
   24501             :                   .FromJust());
   24502          20 :   CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
   24503             :                   .ToLocalChecked()
   24504             :                   ->Int32Value(context.local())
   24505           5 :                   .FromJust());
   24506           5 : }
   24507             : 
   24508       23723 : TEST(PromiseStateAndValue) {
   24509           5 :   LocalContext context;
   24510           5 :   v8::Isolate* isolate = context->GetIsolate();
   24511          10 :   v8::HandleScope scope(isolate);
   24512             :   v8::Local<v8::Value> result = CompileRun(
   24513             :       "var resolver;"
   24514             :       "new Promise((res, rej) => { resolver = res; })");
   24515             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(result);
   24516           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24517             : 
   24518             :   CompileRun("resolver('fulfilled')");
   24519           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24520          10 :   CHECK(v8_str("fulfilled")->SameValue(promise->Result()));
   24521             : 
   24522             :   result = CompileRun("Promise.reject('rejected')");
   24523             :   promise = v8::Local<v8::Promise>::Cast(result);
   24524           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24525          15 :   CHECK(v8_str("rejected")->SameValue(promise->Result()));
   24526           5 : }
   24527             : 
   24528       23718 : TEST(DisallowJavascriptExecutionScope) {
   24529           0 :   LocalContext context;
   24530           0 :   v8::Isolate* isolate = context->GetIsolate();
   24531           0 :   v8::HandleScope scope(isolate);
   24532             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   24533           0 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   24534           0 :   CompileRun("2+2");
   24535           0 : }
   24536             : 
   24537             : 
   24538       23723 : TEST(AllowJavascriptExecutionScope) {
   24539           5 :   LocalContext context;
   24540           5 :   v8::Isolate* isolate = context->GetIsolate();
   24541          10 :   v8::HandleScope scope(isolate);
   24542             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   24543          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   24544             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24545          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   24546           5 :   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   24547           5 :     CompileRun("1+1");
   24548           5 :   }
   24549           5 : }
   24550             : 
   24551             : 
   24552       23723 : TEST(ThrowOnJavascriptExecution) {
   24553           5 :   LocalContext context;
   24554           5 :   v8::Isolate* isolate = context->GetIsolate();
   24555          10 :   v8::HandleScope scope(isolate);
   24556          10 :   v8::TryCatch try_catch(isolate);
   24557             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24558          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   24559             :   CompileRun("1+1");
   24560          10 :   CHECK(try_catch.HasCaught());
   24561           5 : }
   24562             : 
   24563             : 
   24564       23723 : TEST(Regress354123) {
   24565           5 :   LocalContext current;
   24566           5 :   v8::Isolate* isolate = current->GetIsolate();
   24567          10 :   v8::HandleScope scope(isolate);
   24568             : 
   24569           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   24570           5 :   templ->SetAccessCheckCallback(AccessCounter);
   24571          30 :   CHECK(current->Global()
   24572             :             ->Set(current.local(), v8_str("friend"),
   24573             :                   templ->NewInstance(current.local()).ToLocalChecked())
   24574             :             .FromJust());
   24575             : 
   24576             :   // Test access using __proto__ from the prototype chain.
   24577           5 :   access_count = 0;
   24578             :   CompileRun("friend.__proto__ = {};");
   24579           5 :   CHECK_EQ(2, access_count);
   24580             :   CompileRun("friend.__proto__;");
   24581           5 :   CHECK_EQ(4, access_count);
   24582             : 
   24583             :   // Test access using __proto__ as a hijacked function (A).
   24584           5 :   access_count = 0;
   24585             :   CompileRun("var p = Object.prototype;"
   24586             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   24587             :              "f.call(friend, {});");
   24588           5 :   CHECK_EQ(1, access_count);
   24589             :   CompileRun("var p = Object.prototype;"
   24590             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   24591             :              "f.call(friend);");
   24592           5 :   CHECK_EQ(2, access_count);
   24593             : 
   24594             :   // Test access using __proto__ as a hijacked function (B).
   24595           5 :   access_count = 0;
   24596             :   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   24597             :              "f.call(friend, {});");
   24598           5 :   CHECK_EQ(1, access_count);
   24599             :   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   24600             :              "f.call(friend);");
   24601           5 :   CHECK_EQ(2, access_count);
   24602             : 
   24603             :   // Test access using Object.setPrototypeOf reflective method.
   24604           5 :   access_count = 0;
   24605             :   CompileRun("Object.setPrototypeOf(friend, {});");
   24606           5 :   CHECK_EQ(1, access_count);
   24607             :   CompileRun("Object.getPrototypeOf(friend);");
   24608          10 :   CHECK_EQ(2, access_count);
   24609           5 : }
   24610             : 
   24611             : 
   24612       23723 : TEST(CaptureStackTraceForStackOverflow) {
   24613           5 :   v8::internal::FLAG_stack_size = 150;
   24614           5 :   LocalContext current;
   24615           5 :   v8::Isolate* isolate = current->GetIsolate();
   24616          10 :   v8::HandleScope scope(isolate);
   24617             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
   24618           5 :                                                      v8::StackTrace::kDetailed);
   24619          10 :   v8::TryCatch try_catch(isolate);
   24620             :   CompileRun("(function f(x) { f(x+1); })(0)");
   24621          10 :   CHECK(try_catch.HasCaught());
   24622           5 : }
   24623             : 
   24624             : 
   24625       23723 : TEST(ScriptNameAndLineNumber) {
   24626           5 :   LocalContext env;
   24627           5 :   v8::Isolate* isolate = env->GetIsolate();
   24628          10 :   v8::HandleScope scope(isolate);
   24629             :   const char* url = "http://www.foo.com/foo.js";
   24630           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   24631           5 :   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   24632             :   Local<Script> script =
   24633           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   24634          10 :   Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
   24635           5 :   CHECK(!script_name.IsEmpty());
   24636           5 :   CHECK(script_name->IsString());
   24637          10 :   String::Utf8Value utf8_name(env->GetIsolate(), script_name);
   24638           5 :   CHECK_EQ(0, strcmp(url, *utf8_name));
   24639          10 :   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   24640          10 :   CHECK_EQ(13, line_number);
   24641           5 : }
   24642             : 
   24643       23723 : TEST(ScriptPositionInfo) {
   24644           5 :   LocalContext env;
   24645           5 :   v8::Isolate* isolate = env->GetIsolate();
   24646          10 :   v8::HandleScope scope(isolate);
   24647             :   const char* url = "http://www.foo.com/foo.js";
   24648           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   24649             :   v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
   24650             :                                                   "var bar;\n"
   24651             :                                                   "var fisk = foo + bar;\n"),
   24652           5 :                                            origin);
   24653             :   Local<Script> script =
   24654           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   24655             : 
   24656             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   24657          10 :       v8::Utils::OpenHandle(*script->GetUnboundScript()));
   24658           5 :   CHECK(obj->script()->IsScript());
   24659             : 
   24660             :   i::Handle<i::Script> script1(i::Script::cast(obj->script()));
   24661             : 
   24662             :   v8::internal::Script::PositionInfo info;
   24663             : 
   24664          15 :   for (int i = 0; i < 2; ++i) {
   24665             :     // With offset.
   24666             : 
   24667             :     // Behave as if 0 was passed if position is negative.
   24668          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
   24669          10 :     CHECK_EQ(13, info.line);
   24670          10 :     CHECK_EQ(0, info.column);
   24671          10 :     CHECK_EQ(0, info.line_start);
   24672          10 :     CHECK_EQ(8, info.line_end);
   24673             : 
   24674          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
   24675          10 :     CHECK_EQ(13, info.line);
   24676          10 :     CHECK_EQ(0, info.column);
   24677          10 :     CHECK_EQ(0, info.line_start);
   24678          10 :     CHECK_EQ(8, info.line_end);
   24679             : 
   24680          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
   24681          10 :     CHECK_EQ(13, info.line);
   24682          10 :     CHECK_EQ(8, info.column);
   24683          10 :     CHECK_EQ(0, info.line_start);
   24684          10 :     CHECK_EQ(8, info.line_end);
   24685             : 
   24686          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
   24687          10 :     CHECK_EQ(14, info.line);
   24688          10 :     CHECK_EQ(0, info.column);
   24689          10 :     CHECK_EQ(9, info.line_start);
   24690          10 :     CHECK_EQ(17, info.line_end);
   24691             : 
   24692             :     // Fail when position is larger than script size.
   24693          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
   24694             : 
   24695             :     // Without offset.
   24696             : 
   24697             :     // Behave as if 0 was passed if position is negative.
   24698          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
   24699          10 :     CHECK_EQ(0, info.line);
   24700          10 :     CHECK_EQ(0, info.column);
   24701          10 :     CHECK_EQ(0, info.line_start);
   24702          10 :     CHECK_EQ(8, info.line_end);
   24703             : 
   24704          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
   24705          10 :     CHECK_EQ(0, info.line);
   24706          10 :     CHECK_EQ(0, info.column);
   24707          10 :     CHECK_EQ(0, info.line_start);
   24708          10 :     CHECK_EQ(8, info.line_end);
   24709             : 
   24710          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
   24711          10 :     CHECK_EQ(0, info.line);
   24712          10 :     CHECK_EQ(8, info.column);
   24713          10 :     CHECK_EQ(0, info.line_start);
   24714          10 :     CHECK_EQ(8, info.line_end);
   24715             : 
   24716          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
   24717          10 :     CHECK_EQ(1, info.line);
   24718          10 :     CHECK_EQ(0, info.column);
   24719          10 :     CHECK_EQ(9, info.line_start);
   24720          10 :     CHECK_EQ(17, info.line_end);
   24721             : 
   24722             :     // Fail when position is larger than script size.
   24723          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
   24724             : 
   24725          10 :     i::Script::InitLineEnds(script1);
   24726           5 :   }
   24727           5 : }
   24728             : 
   24729         155 : void CheckMagicComments(v8::Isolate* isolate, Local<Script> script,
   24730             :                         const char* expected_source_url,
   24731             :                         const char* expected_source_mapping_url) {
   24732         155 :   if (expected_source_url != nullptr) {
   24733             :     v8::String::Utf8Value url(isolate,
   24734          70 :                               script->GetUnboundScript()->GetSourceURL());
   24735          35 :     CHECK_EQ(0, strcmp(expected_source_url, *url));
   24736             :   } else {
   24737         360 :     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   24738             :   }
   24739         155 :   if (expected_source_mapping_url != nullptr) {
   24740             :     v8::String::Utf8Value url(
   24741          60 :         isolate, script->GetUnboundScript()->GetSourceMappingURL());
   24742          30 :     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
   24743             :   } else {
   24744         375 :     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   24745             :   }
   24746         155 : }
   24747             : 
   24748          70 : void SourceURLHelper(v8::Isolate* isolate, const char* source,
   24749             :                      const char* expected_source_url,
   24750             :                      const char* expected_source_mapping_url) {
   24751          70 :   Local<Script> script = v8_compile(source);
   24752             :   CheckMagicComments(isolate, script, expected_source_url,
   24753          70 :                      expected_source_mapping_url);
   24754          70 : }
   24755             : 
   24756             : 
   24757       23723 : TEST(ScriptSourceURLAndSourceMappingURL) {
   24758           5 :   LocalContext env;
   24759           5 :   v8::Isolate* isolate = env->GetIsolate();
   24760          10 :   v8::HandleScope scope(isolate);
   24761             :   SourceURLHelper(isolate,
   24762             :                   "function foo() {}\n"
   24763             :                   "//# sourceURL=bar1.js\n",
   24764           5 :                   "bar1.js", nullptr);
   24765             :   SourceURLHelper(isolate,
   24766             :                   "function foo() {}\n"
   24767             :                   "//# sourceMappingURL=bar2.js\n",
   24768           5 :                   nullptr, "bar2.js");
   24769             : 
   24770             :   // Both sourceURL and sourceMappingURL.
   24771             :   SourceURLHelper(isolate,
   24772             :                   "function foo() {}\n"
   24773             :                   "//# sourceURL=bar3.js\n"
   24774             :                   "//# sourceMappingURL=bar4.js\n",
   24775           5 :                   "bar3.js", "bar4.js");
   24776             : 
   24777             :   // Two source URLs; the first one is ignored.
   24778             :   SourceURLHelper(isolate,
   24779             :                   "function foo() {}\n"
   24780             :                   "//# sourceURL=ignoreme.js\n"
   24781             :                   "//# sourceURL=bar5.js\n",
   24782           5 :                   "bar5.js", nullptr);
   24783             :   SourceURLHelper(isolate,
   24784             :                   "function foo() {}\n"
   24785             :                   "//# sourceMappingURL=ignoreme.js\n"
   24786             :                   "//# sourceMappingURL=bar6.js\n",
   24787           5 :                   nullptr, "bar6.js");
   24788             : 
   24789             :   // SourceURL or sourceMappingURL in the middle of the script.
   24790             :   SourceURLHelper(isolate,
   24791             :                   "function foo() {}\n"
   24792             :                   "//# sourceURL=bar7.js\n"
   24793             :                   "function baz() {}\n",
   24794           5 :                   "bar7.js", nullptr);
   24795             :   SourceURLHelper(isolate,
   24796             :                   "function foo() {}\n"
   24797             :                   "//# sourceMappingURL=bar8.js\n"
   24798             :                   "function baz() {}\n",
   24799           5 :                   nullptr, "bar8.js");
   24800             : 
   24801             :   // Too much whitespace.
   24802             :   SourceURLHelper(isolate,
   24803             :                   "function foo() {}\n"
   24804             :                   "//#  sourceURL=bar9.js\n"
   24805             :                   "//#  sourceMappingURL=bar10.js\n",
   24806           5 :                   nullptr, nullptr);
   24807             :   SourceURLHelper(isolate,
   24808             :                   "function foo() {}\n"
   24809             :                   "//# sourceURL =bar11.js\n"
   24810             :                   "//# sourceMappingURL =bar12.js\n",
   24811           5 :                   nullptr, nullptr);
   24812             : 
   24813             :   // Disallowed characters in value.
   24814             :   SourceURLHelper(isolate,
   24815             :                   "function foo() {}\n"
   24816             :                   "//# sourceURL=bar13 .js   \n"
   24817             :                   "//# sourceMappingURL=bar14 .js \n",
   24818           5 :                   nullptr, nullptr);
   24819             :   SourceURLHelper(isolate,
   24820             :                   "function foo() {}\n"
   24821             :                   "//# sourceURL=bar15\t.js   \n"
   24822             :                   "//# sourceMappingURL=bar16\t.js \n",
   24823           5 :                   nullptr, nullptr);
   24824             :   SourceURLHelper(isolate,
   24825             :                   "function foo() {}\n"
   24826             :                   "//# sourceURL=bar17'.js   \n"
   24827             :                   "//# sourceMappingURL=bar18'.js \n",
   24828           5 :                   nullptr, nullptr);
   24829             :   SourceURLHelper(isolate,
   24830             :                   "function foo() {}\n"
   24831             :                   "//# sourceURL=bar19\".js   \n"
   24832             :                   "//# sourceMappingURL=bar20\".js \n",
   24833           5 :                   nullptr, nullptr);
   24834             : 
   24835             :   // Not too much whitespace.
   24836             :   SourceURLHelper(isolate,
   24837             :                   "function foo() {}\n"
   24838             :                   "//# sourceURL=  bar21.js   \n"
   24839             :                   "//# sourceMappingURL=  bar22.js \n",
   24840          10 :                   "bar21.js", "bar22.js");
   24841           5 : }
   24842             : 
   24843             : 
   24844       23723 : TEST(GetOwnPropertyDescriptor) {
   24845           5 :   LocalContext env;
   24846           5 :   v8::Isolate* isolate = env->GetIsolate();
   24847          10 :   v8::HandleScope scope(isolate);
   24848             :   CompileRun(
   24849             :       "var x = { value : 13};"
   24850             :       "Object.defineProperty(x, 'p0', {value : 12});"
   24851             :       "Object.defineProperty(x, Symbol.toStringTag, {value: 'foo'});"
   24852             :       "Object.defineProperty(x, 'p1', {"
   24853             :       "  set : function(value) { this.value = value; },"
   24854             :       "  get : function() { return this.value; },"
   24855             :       "});");
   24856             :   Local<Object> x = Local<Object>::Cast(
   24857          25 :       env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
   24858             :   Local<Value> desc =
   24859          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
   24860           5 :           .ToLocalChecked();
   24861           5 :   CHECK(desc->IsUndefined());
   24862             :   desc =
   24863          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
   24864          25 :   CHECK(v8_num(12)
   24865             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   24866             :                                       ->Get(env.local(), v8_str("value"))
   24867             :                                       .ToLocalChecked())
   24868             :             .FromJust());
   24869             :   desc =
   24870          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
   24871             :   Local<Function> set =
   24872             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   24873          15 :                                 ->Get(env.local(), v8_str("set"))
   24874           5 :                                 .ToLocalChecked());
   24875             :   Local<Function> get =
   24876             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   24877          15 :                                 ->Get(env.local(), v8_str("get"))
   24878           5 :                                 .ToLocalChecked());
   24879          20 :   CHECK(v8_num(13)
   24880             :             ->Equals(env.local(),
   24881             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   24882             :             .FromJust());
   24883           5 :   Local<Value> args[] = {v8_num(14)};
   24884          10 :   set->Call(env.local(), x, 1, args).ToLocalChecked();
   24885          20 :   CHECK(v8_num(14)
   24886             :             ->Equals(env.local(),
   24887             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   24888             :             .FromJust());
   24889             :   desc =
   24890          15 :       x->GetOwnPropertyDescriptor(env.local(), Symbol::GetToStringTag(isolate))
   24891           5 :           .ToLocalChecked();
   24892          25 :   CHECK(v8_str("foo")
   24893             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   24894             :                                       ->Get(env.local(), v8_str("value"))
   24895             :                                       .ToLocalChecked())
   24896           5 :             .FromJust());
   24897           5 : }
   24898             : 
   24899             : 
   24900       23723 : TEST(Regress411877) {
   24901           5 :   v8::Isolate* isolate = CcTest::isolate();
   24902           5 :   v8::HandleScope handle_scope(isolate);
   24903             :   v8::Local<v8::ObjectTemplate> object_template =
   24904           5 :       v8::ObjectTemplate::New(isolate);
   24905           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24906             : 
   24907           5 :   v8::Local<Context> context = Context::New(isolate);
   24908             :   v8::Context::Scope context_scope(context);
   24909             : 
   24910          25 :   CHECK(context->Global()
   24911             :             ->Set(context, v8_str("o"),
   24912             :                   object_template->NewInstance(context).ToLocalChecked())
   24913             :             .FromJust());
   24914           5 :   CompileRun("Object.getOwnPropertyNames(o)");
   24915           5 : }
   24916             : 
   24917             : 
   24918       23723 : TEST(GetHiddenPropertyTableAfterAccessCheck) {
   24919           5 :   v8::Isolate* isolate = CcTest::isolate();
   24920           5 :   v8::HandleScope handle_scope(isolate);
   24921             :   v8::Local<v8::ObjectTemplate> object_template =
   24922           5 :       v8::ObjectTemplate::New(isolate);
   24923           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24924             : 
   24925           5 :   v8::Local<Context> context = Context::New(isolate);
   24926             :   v8::Context::Scope context_scope(context);
   24927             : 
   24928             :   v8::Local<v8::Object> obj =
   24929           5 :       object_template->NewInstance(context).ToLocalChecked();
   24930          20 :   obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
   24931          15 :   obj->Delete(context, v8_str("key")).FromJust();
   24932             : 
   24933             :   obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
   24934          15 :                   v8_str("hidden value 2"))
   24935          15 :       .FromJust();
   24936           5 : }
   24937             : 
   24938             : 
   24939       23723 : TEST(Regress411793) {
   24940           5 :   v8::Isolate* isolate = CcTest::isolate();
   24941           5 :   v8::HandleScope handle_scope(isolate);
   24942             :   v8::Local<v8::ObjectTemplate> object_template =
   24943           5 :       v8::ObjectTemplate::New(isolate);
   24944           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24945             : 
   24946           5 :   v8::Local<Context> context = Context::New(isolate);
   24947             :   v8::Context::Scope context_scope(context);
   24948             : 
   24949          25 :   CHECK(context->Global()
   24950             :             ->Set(context, v8_str("o"),
   24951             :                   object_template->NewInstance(context).ToLocalChecked())
   24952             :             .FromJust());
   24953             :   CompileRun(
   24954             :       "Object.defineProperty(o, 'key', "
   24955           5 :       "    { get: function() {}, set: function() {} });");
   24956           5 : }
   24957             : 
   24958         220 : class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   24959             :  public:
   24960         110 :   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   24961             : 
   24962         430 :   virtual size_t GetMoreData(const uint8_t** src) {
   24963             :     // Unlike in real use cases, this function will never block.
   24964         430 :     if (chunks_[index_] == nullptr) {
   24965             :       return 0;
   24966             :     }
   24967             :     // Copy the data, since the caller takes ownership of it.
   24968         330 :     size_t len = strlen(chunks_[index_]);
   24969             :     // We don't need to zero-terminate since we return the length.
   24970         330 :     uint8_t* copy = new uint8_t[len];
   24971         330 :     memcpy(copy, chunks_[index_], len);
   24972         330 :     *src = copy;
   24973         330 :     ++index_;
   24974         330 :     return len;
   24975             :   }
   24976             : 
   24977             :   // Helper for constructing a string from chunks (the compilation needs it
   24978             :   // too).
   24979         105 :   static char* FullSourceString(const char** chunks) {
   24980             :     size_t total_len = 0;
   24981         435 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   24982         330 :       total_len += strlen(chunks[i]);
   24983             :     }
   24984         105 :     char* full_string = new char[total_len + 1];
   24985             :     size_t offset = 0;
   24986         435 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   24987         330 :       size_t len = strlen(chunks[i]);
   24988         330 :       memcpy(full_string + offset, chunks[i], len);
   24989         330 :       offset += len;
   24990             :     }
   24991         105 :     full_string[total_len] = 0;
   24992         105 :     return full_string;
   24993             :   }
   24994             : 
   24995             :  private:
   24996             :   const char** chunks_;
   24997             :   unsigned index_;
   24998             : };
   24999             : 
   25000             : 
   25001             : // Helper function for running streaming tests.
   25002          95 : void RunStreamingTest(const char** chunks,
   25003             :                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   25004             :                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   25005             :                       bool expected_success = true,
   25006             :                       const char* expected_source_url = nullptr,
   25007             :                       const char* expected_source_mapping_url = nullptr) {
   25008          95 :   LocalContext env;
   25009          95 :   v8::Isolate* isolate = env->GetIsolate();
   25010         190 :   v8::HandleScope scope(isolate);
   25011         190 :   v8::TryCatch try_catch(isolate);
   25012             : 
   25013             :   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
   25014         285 :                                             encoding);
   25015             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25016          95 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25017             : 
   25018             :   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   25019             :   // task here in the main thread.
   25020          95 :   task->Run();
   25021          95 :   delete task;
   25022             : 
   25023             :   // Possible errors are only produced while compiling.
   25024          95 :   CHECK(!try_catch.HasCaught());
   25025             : 
   25026          95 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25027          95 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25028             :   v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
   25029          95 :       env.local(), &source, v8_str(full_source), origin);
   25030          95 :   if (expected_success) {
   25031          85 :     CHECK(!script.IsEmpty());
   25032             :     v8::Local<Value> result(
   25033         170 :         script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
   25034             :     // All scripts are supposed to return the fixed value 13 when ran.
   25035         170 :     CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
   25036             :     CheckMagicComments(isolate, script.ToLocalChecked(), expected_source_url,
   25037          85 :                        expected_source_mapping_url);
   25038             :   } else {
   25039          10 :     CHECK(script.IsEmpty());
   25040          10 :     CHECK(try_catch.HasCaught());
   25041             :   }
   25042         190 :   delete[] full_source;
   25043          95 : }
   25044             : 
   25045       23723 : TEST(StreamingSimpleScript) {
   25046             :   // This script is unrealistically small, since no one chunk is enough to fill
   25047             :   // the backing buffer of Scanner, let alone overflow it.
   25048             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   25049           5 :                           nullptr};
   25050           5 :   RunStreamingTest(chunks);
   25051           5 : }
   25052             : 
   25053       23723 : TEST(StreamingScriptConstantArray) {
   25054             :   // When run with Ignition, tests that the streaming parser canonicalizes
   25055             :   // handles so that they are only added to the constant pool array once.
   25056             :   const char* chunks[] = {
   25057             :       "var a = {};",        "var b = {};", "var c = 'testing';",
   25058           5 :       "var d = 'testing';", "13;",         nullptr};
   25059           5 :   RunStreamingTest(chunks);
   25060           5 : }
   25061             : 
   25062       23723 : TEST(StreamingScriptEvalShadowing) {
   25063             :   // When run with Ignition, tests that the streaming parser canonicalizes
   25064             :   // handles so the Variable::is_possibly_eval() is correct.
   25065             :   const char* chunk1 =
   25066             :       "(function() {\n"
   25067             :       "  var y = 2;\n"
   25068             :       "  return (function() {\n"
   25069             :       "    eval('var y = 13;');\n"
   25070             :       "    function g() {\n"
   25071             :       "      return y\n"
   25072             :       "    }\n"
   25073             :       "    return g();\n"
   25074             :       "  })()\n"
   25075             :       "})()\n";
   25076           5 :   const char* chunks[] = {chunk1, nullptr};
   25077           5 :   RunStreamingTest(chunks);
   25078           5 : }
   25079             : 
   25080       23723 : TEST(StreamingBiggerScript) {
   25081             :   const char* chunk1 =
   25082             :       "function foo() {\n"
   25083             :       "  // Make this chunk sufficiently long so that it will overflow the\n"
   25084             :       "  // backing buffer of the Scanner.\n"
   25085             :       "  var i = 0;\n"
   25086             :       "  var result = 0;\n"
   25087             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25088             :       "  result = 0;\n"
   25089             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25090             :       "  result = 0;\n"
   25091             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25092             :       "  result = 0;\n"
   25093             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25094             :       "  return result;\n"
   25095             :       "}\n";
   25096           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   25097           5 :   RunStreamingTest(chunks);
   25098           5 : }
   25099             : 
   25100             : 
   25101       23723 : TEST(StreamingScriptWithParseError) {
   25102             :   // Test that parse errors from streamed scripts are propagated correctly.
   25103             :   {
   25104             :     char chunk1[] =
   25105             :         "  // This will result in a parse error.\n"
   25106           5 :         "  var if else then foo";
   25107           5 :     char chunk2[] = "  13\n";
   25108           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25109             : 
   25110             :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   25111           5 :                      false);
   25112             :   }
   25113             :   // Test that the next script succeeds normally.
   25114             :   {
   25115             :     char chunk1[] =
   25116             :         "  // This will be parsed successfully.\n"
   25117           5 :         "  function foo() { return ";
   25118           5 :     char chunk2[] = "  13; }\n";
   25119           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25120             : 
   25121           5 :     RunStreamingTest(chunks);
   25122             :   }
   25123           5 : }
   25124             : 
   25125             : 
   25126       23723 : TEST(StreamingUtf8Script) {
   25127             :   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
   25128             :   // don't like it.
   25129             :   const char* chunk1 =
   25130             :       "function foo() {\n"
   25131             :       "  // This function will contain an UTF-8 character which is not in\n"
   25132             :       "  // ASCII.\n"
   25133             :       "  var foob\xec\x92\x81r = 13;\n"
   25134             :       "  return foob\xec\x92\x81r;\n"
   25135             :       "}\n";
   25136           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   25137           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25138           5 : }
   25139             : 
   25140             : 
   25141       23723 : TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   25142             :   // A sanity check to prove that the approach of splitting UTF-8
   25143             :   // characters is correct. Here is an UTF-8 character which will take three
   25144             :   // bytes.
   25145             :   const char* reference = "\xec\x92\x81";
   25146             :   CHECK_EQ(3, strlen(reference));
   25147             : 
   25148             :   char chunk1[] =
   25149             :       "function foo() {\n"
   25150             :       "  // This function will contain an UTF-8 character which is not in\n"
   25151             :       "  // ASCII.\n"
   25152           5 :       "  var foob";
   25153             :   char chunk2[] =
   25154             :       "XXXr = 13;\n"
   25155             :       "  return foob\xec\x92\x81r;\n"
   25156           5 :       "}\n";
   25157          20 :   for (int i = 0; i < 3; ++i) {
   25158          15 :     chunk2[i] = reference[i];
   25159             :   }
   25160           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25161           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25162           5 : }
   25163             : 
   25164             : 
   25165       23723 : TEST(StreamingUtf8ScriptWithSplitCharacters) {
   25166             :   // Stream data where a multi-byte UTF-8 character is split between two data
   25167             :   // chunks.
   25168             :   const char* reference = "\xec\x92\x81";
   25169             :   char chunk1[] =
   25170             :       "function foo() {\n"
   25171             :       "  // This function will contain an UTF-8 character which is not in\n"
   25172             :       "  // ASCII.\n"
   25173           5 :       "  var foobX";
   25174             :   char chunk2[] =
   25175             :       "XXr = 13;\n"
   25176             :       "  return foob\xec\x92\x81r;\n"
   25177           5 :       "}\n";
   25178           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25179           5 :   chunk2[0] = reference[1];
   25180           5 :   chunk2[1] = reference[2];
   25181           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25182           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25183           5 : }
   25184             : 
   25185             : 
   25186       23723 : TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   25187             :   // Tests edge cases which should still be decoded correctly.
   25188             : 
   25189             :   // Case 1: a chunk contains only bytes for a split character (and no other
   25190             :   // data). This kind of a chunk would be exceptionally small, but we should
   25191             :   // still decode it correctly.
   25192             :   const char* reference = "\xec\x92\x81";
   25193             :   // The small chunk is at the beginning of the split character
   25194             :   {
   25195             :     char chunk1[] =
   25196             :         "function foo() {\n"
   25197             :         "  // This function will contain an UTF-8 character which is not in\n"
   25198             :         "  // ASCII.\n"
   25199           5 :         "  var foob";
   25200           5 :     char chunk2[] = "XX";
   25201             :     char chunk3[] =
   25202             :         "Xr = 13;\n"
   25203             :         "  return foob\xec\x92\x81r;\n"
   25204           5 :         "}\n";
   25205           5 :     chunk2[0] = reference[0];
   25206           5 :     chunk2[1] = reference[1];
   25207           5 :     chunk3[0] = reference[2];
   25208           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25209           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25210             :   }
   25211             :   // The small chunk is at the end of a character
   25212             :   {
   25213             :     char chunk1[] =
   25214             :         "function foo() {\n"
   25215             :         "  // This function will contain an UTF-8 character which is not in\n"
   25216             :         "  // ASCII.\n"
   25217           5 :         "  var foobX";
   25218           5 :     char chunk2[] = "XX";
   25219             :     char chunk3[] =
   25220             :         "r = 13;\n"
   25221             :         "  return foob\xec\x92\x81r;\n"
   25222           5 :         "}\n";
   25223           5 :     chunk1[strlen(chunk1) - 1] = reference[0];
   25224           5 :     chunk2[0] = reference[1];
   25225           5 :     chunk2[1] = reference[2];
   25226           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25227           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25228             :   }
   25229             :   // Case 2: the script ends with a multi-byte character. Make sure that it's
   25230             :   // decoded correctly and not just ignored.
   25231             :   {
   25232             :     char chunk1[] =
   25233             :         "var foob\xec\x92\x81 = 13;\n"
   25234           5 :         "foob\xec\x92\x81";
   25235           5 :     const char* chunks[] = {chunk1, nullptr};
   25236           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25237             :   }
   25238           5 : }
   25239             : 
   25240             : 
   25241       23723 : TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   25242             :   // Test cases where a UTF-8 character is split over several chunks. Those
   25243             :   // cases are not supported (the embedder should give the data in big enough
   25244             :   // chunks), but we shouldn't crash and parse this just fine.
   25245             :   const char* reference = "\xec\x92\x81";
   25246             :   char chunk1[] =
   25247             :       "function foo() {\n"
   25248             :       "  // This function will contain an UTF-8 character which is not in\n"
   25249             :       "  // ASCII.\n"
   25250           5 :       "  var foobX";
   25251           5 :   char chunk2[] = "X";
   25252             :   char chunk3[] =
   25253             :       "Xr = 13;\n"
   25254             :       "  return foob\xec\x92\x81r;\n"
   25255           5 :       "}\n";
   25256           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25257           5 :   chunk2[0] = reference[1];
   25258           5 :   chunk3[0] = reference[2];
   25259           5 :   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25260             : 
   25261           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25262           5 : }
   25263             : 
   25264             : 
   25265       23723 : TEST(StreamingProducesParserCache) {
   25266             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   25267           5 :                           nullptr};
   25268             : 
   25269           5 :   LocalContext env;
   25270           5 :   v8::Isolate* isolate = env->GetIsolate();
   25271          10 :   v8::HandleScope scope(isolate);
   25272             : 
   25273             :   v8::ScriptCompiler::StreamedSource source(
   25274             :       new TestSourceStream(chunks),
   25275          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25276             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25277             :       v8::ScriptCompiler::StartStreamingScript(
   25278           5 :           isolate, &source, v8::ScriptCompiler::kProduceParserCache);
   25279             : 
   25280             :   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   25281             :   // task here in the main thread.
   25282           5 :   task->Run();
   25283           5 :   delete task;
   25284             : 
   25285           5 :   const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
   25286           5 :   CHECK_NOT_NULL(cached_data);
   25287           5 :   CHECK_NOT_NULL(cached_data->data);
   25288           5 :   CHECK(!cached_data->rejected);
   25289          10 :   CHECK_GT(cached_data->length, 0);
   25290           5 : }
   25291             : 
   25292             : 
   25293       23723 : TEST(StreamingWithDebuggingEnabledLate) {
   25294             :   // The streaming parser can only parse lazily, i.e. inner functions are not
   25295             :   // fully parsed. However, we may compile inner functions eagerly when
   25296             :   // debugging. Make sure that we can deal with this when turning on debugging
   25297             :   // after streaming parser has already finished parsing.
   25298             :   const char* chunks[] = {"with({x:1}) {",
   25299             :                           "  var foo = function foo(y) {",
   25300             :                           "    return x + y;",
   25301             :                           "  };",
   25302             :                           "  foo(2);",
   25303             :                           "}",
   25304           5 :                           nullptr};
   25305             : 
   25306           5 :   LocalContext env;
   25307           5 :   v8::Isolate* isolate = env->GetIsolate();
   25308          10 :   v8::HandleScope scope(isolate);
   25309          10 :   v8::TryCatch try_catch(isolate);
   25310             : 
   25311             :   v8::ScriptCompiler::StreamedSource source(
   25312             :       new TestSourceStream(chunks),
   25313          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25314             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25315           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25316             : 
   25317           5 :   task->Run();
   25318           5 :   delete task;
   25319             : 
   25320           5 :   CHECK(!try_catch.HasCaught());
   25321             : 
   25322           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25323           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25324             : 
   25325             :   EnableDebugger(isolate);
   25326             : 
   25327             :   v8::Local<Script> script =
   25328             :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25329           5 :                                   origin)
   25330           5 :           .ToLocalChecked();
   25331             : 
   25332             :   Maybe<uint32_t> result =
   25333          10 :       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
   25334           5 :   CHECK_EQ(3U, result.FromMaybe(0));
   25335             : 
   25336           5 :   delete[] full_source;
   25337             : 
   25338           5 :   DisableDebugger(isolate);
   25339           5 : }
   25340             : 
   25341             : 
   25342       23723 : TEST(StreamingScriptWithInvalidUtf8) {
   25343             :   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   25344             :   // chunk don't produce a crash.
   25345             :   const char* reference = "\xec\x92\x81\x80\x80";
   25346             :   char chunk1[] =
   25347             :       "function foo() {\n"
   25348             :       "  // This function will contain an UTF-8 character which is not in\n"
   25349             :       "  // ASCII.\n"
   25350           5 :       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   25351             :   char chunk2[] =
   25352             :       "r = 13;\n"
   25353             :       "  return foob\xec\x92\x81\x80\x80r;\n"
   25354           5 :       "}\n";
   25355           5 :   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   25356             : 
   25357           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25358           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   25359           5 : }
   25360             : 
   25361             : 
   25362       23723 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
   25363             :   // Regression test: Stream data where there are several multi-byte UTF-8
   25364             :   // characters in a sequence and one of them is split between two data chunks.
   25365             :   const char* reference = "\xec\x92\x81";
   25366             :   char chunk1[] =
   25367             :       "function foo() {\n"
   25368             :       "  // This function will contain an UTF-8 character which is not in\n"
   25369             :       "  // ASCII.\n"
   25370           5 :       "  var foob\xec\x92\x81X";
   25371             :   char chunk2[] =
   25372             :       "XXr = 13;\n"
   25373             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25374           5 :       "}\n";
   25375           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25376           5 :   chunk2[0] = reference[1];
   25377           5 :   chunk2[1] = reference[2];
   25378           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25379           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25380           5 : }
   25381             : 
   25382             : 
   25383       23723 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
   25384             :   // Another regression test, similar to the previous one. The difference is
   25385             :   // that the split character is not the last one in the sequence.
   25386             :   const char* reference = "\xec\x92\x81";
   25387             :   char chunk1[] =
   25388             :       "function foo() {\n"
   25389             :       "  // This function will contain an UTF-8 character which is not in\n"
   25390             :       "  // ASCII.\n"
   25391           5 :       "  var foobX";
   25392             :   char chunk2[] =
   25393             :       "XX\xec\x92\x81r = 13;\n"
   25394             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25395           5 :       "}\n";
   25396           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25397           5 :   chunk2[0] = reference[1];
   25398           5 :   chunk2[1] = reference[2];
   25399           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25400           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25401           5 : }
   25402             : 
   25403             : 
   25404       23723 : TEST(StreamingWithHarmonyScopes) {
   25405             :   // Don't use RunStreamingTest here so that both scripts get to use the same
   25406             :   // LocalContext and HandleScope.
   25407           5 :   LocalContext env;
   25408           5 :   v8::Isolate* isolate = env->GetIsolate();
   25409          10 :   v8::HandleScope scope(isolate);
   25410             : 
   25411             :   // First, run a script with a let variable.
   25412             :   CompileRun("\"use strict\"; let x = 1;");
   25413             : 
   25414             :   // Then stream a script which (erroneously) tries to introduce the same
   25415             :   // variable again.
   25416           5 :   const char* chunks[] = {"\"use strict\"; let x = 2;", nullptr};
   25417             : 
   25418          10 :   v8::TryCatch try_catch(isolate);
   25419             :   v8::ScriptCompiler::StreamedSource source(
   25420             :       new TestSourceStream(chunks),
   25421          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25422             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25423           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25424           5 :   task->Run();
   25425           5 :   delete task;
   25426             : 
   25427             :   // Parsing should succeed (the script will be parsed and compiled in a context
   25428             :   // independent way, so the error is not detected).
   25429           5 :   CHECK(!try_catch.HasCaught());
   25430             : 
   25431           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25432           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25433             :   v8::Local<Script> script =
   25434             :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25435           5 :                                   origin)
   25436           5 :           .ToLocalChecked();
   25437           5 :   CHECK(!script.IsEmpty());
   25438           5 :   CHECK(!try_catch.HasCaught());
   25439             : 
   25440             :   // Running the script exposes the error.
   25441          10 :   CHECK(script->Run(env.local()).IsEmpty());
   25442           5 :   CHECK(try_catch.HasCaught());
   25443          10 :   delete[] full_source;
   25444           5 : }
   25445             : 
   25446             : 
   25447       23723 : TEST(CodeCache) {
   25448             :   v8::Isolate::CreateParams create_params;
   25449           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25450             : 
   25451             :   const char* source = "Math.sqrt(4)";
   25452             :   const char* origin = "code cache test";
   25453             :   v8::ScriptCompiler::CachedData* cache;
   25454             : 
   25455           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   25456             :   {
   25457             :     v8::Isolate::Scope iscope(isolate1);
   25458          10 :     v8::HandleScope scope(isolate1);
   25459           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   25460             :     v8::Context::Scope cscope(context);
   25461           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25462           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25463             :     v8::ScriptCompiler::Source source(source_string, script_origin);
   25464             :     v8::ScriptCompiler::CompileOptions option =
   25465             :         v8::ScriptCompiler::kProduceCodeCache;
   25466           5 :     v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25467           5 :     int length = source.GetCachedData()->length;
   25468           5 :     uint8_t* cache_data = new uint8_t[length];
   25469           5 :     memcpy(cache_data, source.GetCachedData()->data, length);
   25470             :     cache = new v8::ScriptCompiler::CachedData(
   25471           5 :         cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
   25472             :   }
   25473           5 :   isolate1->Dispose();
   25474             : 
   25475           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   25476             :   {
   25477             :     v8::Isolate::Scope iscope(isolate2);
   25478          10 :     v8::HandleScope scope(isolate2);
   25479           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   25480             :     v8::Context::Scope cscope(context);
   25481           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25482           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25483             :     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
   25484             :     v8::ScriptCompiler::CompileOptions option =
   25485             :         v8::ScriptCompiler::kConsumeCodeCache;
   25486             :     v8::Local<v8::Script> script;
   25487             :     {
   25488             :       i::DisallowCompilation no_compile(
   25489             :           reinterpret_cast<i::Isolate*>(isolate2));
   25490             :       script = v8::ScriptCompiler::Compile(context, &source, option)
   25491           5 :                    .ToLocalChecked();
   25492             :     }
   25493          20 :     CHECK_EQ(2, script->Run(context)
   25494             :                     .ToLocalChecked()
   25495             :                     ->ToInt32(context)
   25496             :                     .ToLocalChecked()
   25497             :                     ->Int32Value(context)
   25498             :                     .FromJust());
   25499             :   }
   25500           5 :   isolate2->Dispose();
   25501           5 : }
   25502             : 
   25503             : 
   25504          10 : void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
   25505             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   25506             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   25507             :   int length = 16;
   25508             :   v8::ScriptCompiler::CachedData* cached_data =
   25509          10 :       new v8::ScriptCompiler::CachedData(data, length);
   25510          10 :   CHECK(!cached_data->rejected);
   25511          10 :   v8::ScriptOrigin origin(v8_str("origin"));
   25512          10 :   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
   25513          10 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   25514             :   v8::Local<v8::Script> script =
   25515          10 :       v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25516          10 :   CHECK(cached_data->rejected);
   25517          30 :   CHECK_EQ(
   25518             :       42,
   25519             :       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
   25520          10 : }
   25521             : 
   25522       23723 : TEST(InvalidParserCacheData) {
   25523           5 :   v8::V8::Initialize();
   25524           5 :   v8::HandleScope scope(CcTest::isolate());
   25525          10 :   LocalContext context;
   25526           5 :   if (i::FLAG_lazy) {
   25527             :     // Cached parser data is not consumed while parsing eagerly.
   25528           5 :     TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
   25529           5 :   }
   25530           5 : }
   25531             : 
   25532       23723 : TEST(InvalidCodeCacheData) {
   25533           5 :   v8::V8::Initialize();
   25534           5 :   v8::HandleScope scope(CcTest::isolate());
   25535          10 :   LocalContext context;
   25536          10 :   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
   25537           5 : }
   25538             : 
   25539             : 
   25540       23723 : TEST(ParserCacheRejectedGracefully) {
   25541             :   // Producing cached parser data while parsing eagerly is not supported.
   25542           5 :   if (!i::FLAG_lazy) return;
   25543             : 
   25544           5 :   v8::V8::Initialize();
   25545           5 :   v8::HandleScope scope(CcTest::isolate());
   25546          10 :   LocalContext context;
   25547             :   // Produce valid cached data.
   25548           5 :   v8::ScriptOrigin origin(v8_str("origin"));
   25549           5 :   v8::Local<v8::String> source_str = v8_str("function foo() {}");
   25550             :   v8::ScriptCompiler::Source source(source_str, origin);
   25551             :   v8::Local<v8::Script> script =
   25552             :       v8::ScriptCompiler::Compile(context.local(), &source,
   25553           5 :                                   v8::ScriptCompiler::kProduceParserCache)
   25554           5 :           .ToLocalChecked();
   25555             :   USE(script);
   25556             :   const v8::ScriptCompiler::CachedData* original_cached_data =
   25557           5 :       source.GetCachedData();
   25558           5 :   CHECK_NOT_NULL(original_cached_data);
   25559           5 :   CHECK_NOT_NULL(original_cached_data->data);
   25560           5 :   CHECK(!original_cached_data->rejected);
   25561           5 :   CHECK_GT(original_cached_data->length, 0);
   25562             :   // Recompiling the same script with it won't reject the data.
   25563             :   {
   25564             :     v8::ScriptCompiler::Source source_with_cached_data(
   25565             :         source_str, origin,
   25566             :         new v8::ScriptCompiler::CachedData(original_cached_data->data,
   25567           5 :                                            original_cached_data->length));
   25568             :     v8::Local<v8::Script> script =
   25569             :         v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
   25570           5 :                                     v8::ScriptCompiler::kConsumeParserCache)
   25571           5 :             .ToLocalChecked();
   25572             :     USE(script);
   25573             :     const v8::ScriptCompiler::CachedData* new_cached_data =
   25574           5 :         source_with_cached_data.GetCachedData();
   25575           5 :     CHECK_NOT_NULL(new_cached_data);
   25576           5 :     CHECK(!new_cached_data->rejected);
   25577             :   }
   25578             :   // Compile an incompatible script with the cached data. The new script doesn't
   25579             :   // have the same starting position for the function as the old one, so the old
   25580             :   // cached data will be incompatible with it and will be rejected.
   25581             :   {
   25582             :     v8::Local<v8::String> incompatible_source_str =
   25583           5 :         v8_str("   function foo() {}");
   25584             :     v8::ScriptCompiler::Source source_with_cached_data(
   25585             :         incompatible_source_str, origin,
   25586             :         new v8::ScriptCompiler::CachedData(original_cached_data->data,
   25587           5 :                                            original_cached_data->length));
   25588             :     v8::Local<v8::Script> script =
   25589             :         v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
   25590           5 :                                     v8::ScriptCompiler::kConsumeParserCache)
   25591           5 :             .ToLocalChecked();
   25592             :     USE(script);
   25593             :     const v8::ScriptCompiler::CachedData* new_cached_data =
   25594           5 :         source_with_cached_data.GetCachedData();
   25595           5 :     CHECK_NOT_NULL(new_cached_data);
   25596           5 :     CHECK(new_cached_data->rejected);
   25597           5 :   }
   25598             : }
   25599             : 
   25600             : 
   25601       23723 : TEST(StringConcatOverflow) {
   25602           5 :   v8::V8::Initialize();
   25603           5 :   v8::HandleScope scope(CcTest::isolate());
   25604             :   RandomLengthOneByteResource* r =
   25605           5 :       new RandomLengthOneByteResource(i::String::kMaxLength);
   25606             :   v8::Local<v8::String> str =
   25607           5 :       v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
   25608           5 :   CHECK(!str.IsEmpty());
   25609          10 :   v8::TryCatch try_catch(CcTest::isolate());
   25610           5 :   v8::Local<v8::String> result = v8::String::Concat(str, str);
   25611           5 :   CHECK(result.IsEmpty());
   25612          10 :   CHECK(!try_catch.HasCaught());
   25613           5 : }
   25614             : 
   25615       23723 : TEST(TurboAsmDisablesNeuter) {
   25616           5 :   i::FLAG_opt = true;
   25617           5 :   i::FLAG_allow_natives_syntax = true;
   25618           5 :   v8::V8::Initialize();
   25619           5 :   v8::HandleScope scope(CcTest::isolate());
   25620          10 :   LocalContext context;
   25621             :   const char* load =
   25622             :       "function Module(stdlib, foreign, heap) {"
   25623             :       "  'use asm';"
   25624             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   25625             :       "  function load() { return MEM32[0] | 0; }"
   25626             :       "  return { load: load };"
   25627             :       "}"
   25628             :       "var buffer = new ArrayBuffer(1024);"
   25629             :       "var module = Module(this, {}, buffer);"
   25630             :       "%OptimizeFunctionOnNextCall(module.load);"
   25631             :       "module.load();"
   25632             :       "buffer";
   25633             : 
   25634             :   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   25635           5 :   CHECK(!result->IsNeuterable());
   25636             : 
   25637             :   const char* store =
   25638             :       "function Module(stdlib, foreign, heap) {"
   25639             :       "  'use asm';"
   25640             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   25641             :       "  function store() { MEM32[0] = 0; }"
   25642             :       "  return { store: store };"
   25643             :       "}"
   25644             :       "var buffer = new ArrayBuffer(1024);"
   25645             :       "var module = Module(this, {}, buffer);"
   25646             :       "%OptimizeFunctionOnNextCall(module.store);"
   25647             :       "module.store();"
   25648             :       "buffer";
   25649             : 
   25650             :   result = CompileRun(store).As<v8::ArrayBuffer>();
   25651          10 :   CHECK(!result->IsNeuterable());
   25652           5 : }
   25653             : 
   25654       23723 : TEST(GetPrototypeAccessControl) {
   25655           5 :   i::FLAG_allow_natives_syntax = true;
   25656           5 :   v8::Isolate* isolate = CcTest::isolate();
   25657           5 :   v8::HandleScope handle_scope(isolate);
   25658          10 :   LocalContext env;
   25659             : 
   25660           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   25661           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   25662             : 
   25663          30 :   CHECK(env->Global()
   25664             :             ->Set(env.local(), v8_str("prohibited"),
   25665             :                   obj_template->NewInstance(env.local()).ToLocalChecked())
   25666             :             .FromJust());
   25667             : 
   25668           5 :   CHECK(CompileRun(
   25669             :             "function f() { return %_GetPrototype(prohibited); }"
   25670             :             "%OptimizeFunctionOnNextCall(f);"
   25671           5 :             "f();")->IsNull());
   25672           5 : }
   25673             : 
   25674             : 
   25675       23723 : TEST(GetPrototypeHidden) {
   25676           5 :   i::FLAG_allow_natives_syntax = true;
   25677           5 :   v8::Isolate* isolate = CcTest::isolate();
   25678           5 :   v8::HandleScope handle_scope(isolate);
   25679          10 :   LocalContext env;
   25680             : 
   25681           5 :   Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
   25682           5 :   t->SetHiddenPrototype(true);
   25683           5 :   Local<Object> proto = t->GetFunction(env.local())
   25684           5 :                             .ToLocalChecked()
   25685           5 :                             ->NewInstance(env.local())
   25686             :                             .ToLocalChecked();
   25687           5 :   Local<Object> object = Object::New(isolate);
   25688           5 :   Local<Object> proto2 = Object::New(isolate);
   25689          15 :   object->SetPrototype(env.local(), proto).FromJust();
   25690          10 :   proto->SetPrototype(env.local(), proto2).FromJust();
   25691             : 
   25692          25 :   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   25693          25 :   CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
   25694          25 :   CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
   25695             : 
   25696             :   v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
   25697          10 :   CHECK(result->Equals(env.local(), proto2).FromJust());
   25698             : 
   25699             :   result = CompileRun(
   25700             :       "function f() { return %_GetPrototype(object); }"
   25701             :       "%OptimizeFunctionOnNextCall(f);"
   25702             :       "f()");
   25703          15 :   CHECK(result->Equals(env.local(), proto2).FromJust());
   25704           5 : }
   25705             : 
   25706             : 
   25707       23723 : TEST(ClassPrototypeCreationContext) {
   25708           5 :   v8::Isolate* isolate = CcTest::isolate();
   25709           5 :   v8::HandleScope handle_scope(isolate);
   25710          10 :   LocalContext env;
   25711             : 
   25712             :   Local<Object> result = Local<Object>::Cast(
   25713             :       CompileRun("'use strict'; class Example { }; Example.prototype"));
   25714          15 :   CHECK(env.local() == result->CreationContext());
   25715           5 : }
   25716             : 
   25717             : 
   25718       23723 : TEST(SimpleStreamingScriptWithSourceURL) {
   25719             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
   25720           5 :                           "//# sourceURL=bar2.js\n", nullptr};
   25721             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25722           5 :                    "bar2.js");
   25723           5 : }
   25724             : 
   25725             : 
   25726       23723 : TEST(StreamingScriptWithSplitSourceURL) {
   25727             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
   25728           5 :                           "oo();\n//# sourceURL=b", "ar2.js\n", nullptr};
   25729             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25730           5 :                    "bar2.js");
   25731           5 : }
   25732             : 
   25733             : 
   25734       23723 : TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
   25735             :   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
   25736           5 :                           " sourceMappingURL=bar2.js\n", "foo();", nullptr};
   25737             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25738           5 :                    nullptr, "bar2.js");
   25739           5 : }
   25740             : 
   25741             : 
   25742       23723 : TEST(NewStringRangeError) {
   25743             :   // This test uses a lot of memory and fails with flaky OOM when run
   25744             :   // with --stress-incremental-marking on TSAN.
   25745           5 :   i::FLAG_stress_incremental_marking = false;
   25746           5 :   v8::Isolate* isolate = CcTest::isolate();
   25747           5 :   v8::HandleScope handle_scope(isolate);
   25748             :   const int length = i::String::kMaxLength + 1;
   25749             :   const int buffer_size = length * sizeof(uint16_t);
   25750           5 :   void* buffer = malloc(buffer_size);
   25751           5 :   if (buffer == nullptr) return;
   25752             :   memset(buffer, 'A', buffer_size);
   25753             :   {
   25754           5 :     v8::TryCatch try_catch(isolate);
   25755             :     char* data = reinterpret_cast<char*>(buffer);
   25756          10 :     CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
   25757             :                                   length)
   25758             :               .IsEmpty());
   25759           5 :     CHECK(!try_catch.HasCaught());
   25760             :   }
   25761             :   {
   25762           5 :     v8::TryCatch try_catch(isolate);
   25763             :     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
   25764          10 :     CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
   25765             :                                      length)
   25766             :               .IsEmpty());
   25767           5 :     CHECK(!try_catch.HasCaught());
   25768             :   }
   25769             :   {
   25770           5 :     v8::TryCatch try_catch(isolate);
   25771             :     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
   25772          10 :     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
   25773             :                                      length)
   25774             :               .IsEmpty());
   25775           5 :     CHECK(!try_catch.HasCaught());
   25776             :   }
   25777           5 :   free(buffer);
   25778             : }
   25779             : 
   25780             : 
   25781       23718 : TEST(SealHandleScope) {
   25782           0 :   v8::Isolate* isolate = CcTest::isolate();
   25783           0 :   v8::HandleScope handle_scope(isolate);
   25784           0 :   LocalContext env;
   25785             : 
   25786           0 :   v8::SealHandleScope seal(isolate);
   25787             : 
   25788             :   // Should fail
   25789           0 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25790             : 
   25791           0 :   USE(obj);
   25792           0 : }
   25793             : 
   25794             : 
   25795       23723 : TEST(SealHandleScopeNested) {
   25796           5 :   v8::Isolate* isolate = CcTest::isolate();
   25797           5 :   v8::HandleScope handle_scope(isolate);
   25798          10 :   LocalContext env;
   25799             : 
   25800          10 :   v8::SealHandleScope seal(isolate);
   25801             : 
   25802             :   {
   25803           5 :     v8::HandleScope handle_scope(isolate);
   25804             : 
   25805             :     // Should work
   25806           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25807             : 
   25808           5 :     USE(obj);
   25809           5 :   }
   25810           5 : }
   25811             : 
   25812             : 
   25813          10 : static void ExtrasBindingTestRuntimeFunction(
   25814          20 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   25815          30 :   CHECK_EQ(
   25816             :       3,
   25817             :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
   25818          10 :   args.GetReturnValue().Set(v8_num(7));
   25819          10 : }
   25820             : 
   25821       23723 : TEST(ExtrasFunctionSource) {
   25822           5 :   v8::Isolate* isolate = CcTest::isolate();
   25823           5 :   v8::HandleScope handle_scope(isolate);
   25824          10 :   LocalContext env;
   25825             : 
   25826           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25827             : 
   25828             :   // Functions defined in extras do not expose source code.
   25829          15 :   auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
   25830           5 :                   .ToLocalChecked()
   25831             :                   .As<v8::Function>();
   25832             :   auto undefined = v8::Undefined(isolate);
   25833          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25834           5 :                     .ToLocalChecked()
   25835             :                     .As<v8::String>();
   25836          10 :   CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
   25837             : 
   25838             :   // Functions defined in extras do not show up in the stack trace.
   25839          15 :   auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
   25840           5 :                      .ToLocalChecked()
   25841             :                      .As<v8::Function>();
   25842          25 :   CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
   25843             :   ExpectString(
   25844             :       "function f(x) { return wrapper(x) }"
   25845             :       "function g() { return new Error().stack; }"
   25846             :       "f(g)",
   25847             :       "Error\n"
   25848             :       "    at g (<anonymous>:1:58)\n"
   25849             :       "    at f (<anonymous>:1:24)\n"
   25850          10 :       "    at <anonymous>:1:78");
   25851           5 : }
   25852             : 
   25853       23723 : TEST(ExtrasBindingObject) {
   25854           5 :   v8::Isolate* isolate = CcTest::isolate();
   25855           5 :   v8::HandleScope handle_scope(isolate);
   25856          10 :   LocalContext env;
   25857             : 
   25858             :   // standalone.gypi ensures we include the test-extra.js file, which should
   25859             :   // export the tested functions.
   25860           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25861             : 
   25862          15 :   auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
   25863           5 :                   .ToLocalChecked()
   25864             :                   .As<v8::Function>();
   25865             :   auto undefined = v8::Undefined(isolate);
   25866          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25867           5 :                     .ToLocalChecked()
   25868             :                     .As<v8::Number>();
   25869          10 :   CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
   25870             : 
   25871             :   v8::Local<v8::FunctionTemplate> runtimeFunction =
   25872           5 :       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   25873             :   binding->Set(env.local(), v8_str("runtime"),
   25874          25 :                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   25875          10 :       .FromJust();
   25876          15 :   func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
   25877           5 :              .ToLocalChecked()
   25878             :              .As<v8::Function>();
   25879          10 :   result = func->Call(env.local(), undefined, 0, {})
   25880           5 :                .ToLocalChecked()
   25881             :                .As<v8::Number>();
   25882          15 :   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   25883           5 : }
   25884             : 
   25885             : 
   25886       23723 : TEST(ExperimentalExtras) {
   25887           5 :   i::FLAG_experimental_extras = true;
   25888             : 
   25889           5 :   v8::Isolate* isolate = CcTest::isolate();
   25890           5 :   v8::HandleScope handle_scope(isolate);
   25891          10 :   LocalContext env;
   25892             : 
   25893             :   // standalone.gypi ensures we include the test-experimental-extra.js file,
   25894             :   // which should export the tested functions.
   25895           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25896             : 
   25897             :   auto func =
   25898          15 :       binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
   25899           5 :           .ToLocalChecked()
   25900             :           .As<v8::Function>();
   25901             :   auto undefined = v8::Undefined(isolate);
   25902          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25903           5 :                     .ToLocalChecked()
   25904             :                     .As<v8::Number>();
   25905          10 :   CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
   25906             : 
   25907             :   v8::Local<v8::FunctionTemplate> runtimeFunction =
   25908           5 :       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   25909             :   binding->Set(env.local(), v8_str("runtime"),
   25910          25 :                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   25911          10 :       .FromJust();
   25912             :   func = binding->Get(env.local(),
   25913          15 :                       v8_str("testExperimentalExtraShouldCallToRuntime"))
   25914           5 :              .ToLocalChecked()
   25915             :              .As<v8::Function>();
   25916          10 :   result = func->Call(env.local(), undefined, 0, {})
   25917           5 :                .ToLocalChecked()
   25918             :                .As<v8::Number>();
   25919          15 :   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   25920           5 : }
   25921             : 
   25922             : 
   25923       23723 : TEST(ExtrasUtilsObject) {
   25924           5 :   LocalContext context;
   25925           5 :   v8::Isolate* isolate = context->GetIsolate();
   25926          10 :   v8::HandleScope handle_scope(isolate);
   25927             : 
   25928          10 :   LocalContext env;
   25929           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25930             : 
   25931          15 :   auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
   25932           5 :                   .ToLocalChecked()
   25933             :                   .As<v8::Function>();
   25934             :   auto undefined = v8::Undefined(isolate);
   25935          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25936           5 :                     .ToLocalChecked()
   25937             :                     .As<v8::Object>();
   25938             : 
   25939          15 :   auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
   25940           5 :                             .ToLocalChecked()
   25941             :                             .As<v8::Symbol>();
   25942             :   i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
   25943           5 :   CHECK(ips->IsPrivate());
   25944             : 
   25945             :   CompileRun("var result = 0; function store(x) { result = x; }");
   25946           5 :   auto store = CompileRun("store").As<v8::Function>();
   25947             : 
   25948          15 :   auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
   25949           5 :                                .ToLocalChecked()
   25950             :                                .As<v8::Promise>();
   25951           5 :   fulfilled_promise->Then(env.local(), store).ToLocalChecked();
   25952           5 :   isolate->RunMicrotasks();
   25953          15 :   CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
   25954             : 
   25955             :   auto fulfilled_promise_2 =
   25956          15 :       result->Get(env.local(), v8_str("fulfilledPromise2"))
   25957           5 :           .ToLocalChecked()
   25958             :           .As<v8::Promise>();
   25959           5 :   fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
   25960           5 :   isolate->RunMicrotasks();
   25961          15 :   CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
   25962             : 
   25963          15 :   auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
   25964           5 :                               .ToLocalChecked()
   25965             :                               .As<v8::Promise>();
   25966           5 :   rejected_promise->Catch(env.local(), store).ToLocalChecked();
   25967           5 :   isolate->RunMicrotasks();
   25968          15 :   CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
   25969             : 
   25970             :   auto rejected_but_handled_promise =
   25971          15 :       result->Get(env.local(), v8_str("rejectedButHandledPromise"))
   25972           5 :           .ToLocalChecked()
   25973             :           .As<v8::Promise>();
   25974           5 :   CHECK(rejected_but_handled_promise->HasHandler());
   25975             : 
   25976          15 :   auto promise_states = result->Get(env.local(), v8_str("promiseStates"))
   25977           5 :                             .ToLocalChecked()
   25978             :                             .As<v8::String>();
   25979          10 :   String::Utf8Value promise_states_string(isolate, promise_states);
   25980           5 :   CHECK_EQ(0, strcmp(*promise_states_string, "pending fulfilled rejected"));
   25981             : 
   25982          15 :   auto promise_is_promise = result->Get(env.local(), v8_str("promiseIsPromise"))
   25983           5 :                                 .ToLocalChecked()
   25984             :                                 .As<v8::Boolean>();
   25985           5 :   CHECK_EQ(true, promise_is_promise->Value());
   25986             : 
   25987             :   auto thenable_is_promise =
   25988          15 :       result->Get(env.local(), v8_str("thenableIsPromise"))
   25989           5 :           .ToLocalChecked()
   25990             :           .As<v8::Boolean>();
   25991          15 :   CHECK_EQ(false, thenable_is_promise->Value());
   25992           5 : }
   25993             : 
   25994             : 
   25995       23723 : TEST(Map) {
   25996           5 :   v8::Isolate* isolate = CcTest::isolate();
   25997           5 :   v8::HandleScope handle_scope(isolate);
   25998          10 :   LocalContext env;
   25999             : 
   26000           5 :   v8::Local<v8::Map> map = v8::Map::New(isolate);
   26001           5 :   CHECK(map->IsObject());
   26002           5 :   CHECK(map->IsMap());
   26003          10 :   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
   26004           5 :   CHECK_EQ(0U, map->Size());
   26005             : 
   26006             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
   26007           5 :   CHECK(val->IsMap());
   26008             :   map = v8::Local<v8::Map>::Cast(val);
   26009           5 :   CHECK_EQ(2U, map->Size());
   26010             : 
   26011           5 :   v8::Local<v8::Array> contents = map->AsArray();
   26012           5 :   CHECK_EQ(4U, contents->Length());
   26013          10 :   CHECK_EQ(
   26014             :       1,
   26015             :       contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26016          10 :   CHECK_EQ(
   26017             :       2,
   26018             :       contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26019          10 :   CHECK_EQ(
   26020             :       3,
   26021             :       contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
   26022          10 :   CHECK_EQ(
   26023             :       4,
   26024             :       contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
   26025             : 
   26026           5 :   CHECK_EQ(2U, map->Size());
   26027             : 
   26028          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26029          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26030             : 
   26031          15 :   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26032          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26033             : 
   26034          20 :   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
   26035             :                   .ToLocalChecked()
   26036             :                   ->Int32Value(env.local())
   26037             :                   .FromJust());
   26038          20 :   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
   26039             :                   .ToLocalChecked()
   26040             :                   ->Int32Value(env.local())
   26041             :                   .FromJust());
   26042             : 
   26043          15 :   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
   26044             :             .ToLocalChecked()
   26045             :             ->IsUndefined());
   26046             : 
   26047          10 :   CHECK(!map->Set(env.local(), map, map).IsEmpty());
   26048           5 :   CHECK_EQ(3U, map->Size());
   26049          10 :   CHECK(map->Has(env.local(), map).FromJust());
   26050             : 
   26051          10 :   CHECK(map->Delete(env.local(), map).FromJust());
   26052           5 :   CHECK_EQ(2U, map->Size());
   26053          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26054          10 :   CHECK(!map->Delete(env.local(), map).FromJust());
   26055             : 
   26056           5 :   map->Clear();
   26057          10 :   CHECK_EQ(0U, map->Size());
   26058           5 : }
   26059             : 
   26060             : 
   26061       23723 : TEST(Set) {
   26062           5 :   v8::Isolate* isolate = CcTest::isolate();
   26063           5 :   v8::HandleScope handle_scope(isolate);
   26064          10 :   LocalContext env;
   26065             : 
   26066           5 :   v8::Local<v8::Set> set = v8::Set::New(isolate);
   26067           5 :   CHECK(set->IsObject());
   26068           5 :   CHECK(set->IsSet());
   26069          10 :   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
   26070           5 :   CHECK_EQ(0U, set->Size());
   26071             : 
   26072             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
   26073           5 :   CHECK(val->IsSet());
   26074             :   set = v8::Local<v8::Set>::Cast(val);
   26075           5 :   CHECK_EQ(2U, set->Size());
   26076             : 
   26077           5 :   v8::Local<v8::Array> keys = set->AsArray();
   26078           5 :   CHECK_EQ(2U, keys->Length());
   26079          10 :   CHECK_EQ(1,
   26080             :            keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26081          10 :   CHECK_EQ(2,
   26082             :            keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26083             : 
   26084           5 :   CHECK_EQ(2U, set->Size());
   26085             : 
   26086          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26087          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26088             : 
   26089          15 :   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26090          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26091             : 
   26092          10 :   CHECK(!set->Add(env.local(), set).IsEmpty());
   26093           5 :   CHECK_EQ(3U, set->Size());
   26094          10 :   CHECK(set->Has(env.local(), set).FromJust());
   26095             : 
   26096          10 :   CHECK(set->Delete(env.local(), set).FromJust());
   26097           5 :   CHECK_EQ(2U, set->Size());
   26098          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26099          10 :   CHECK(!set->Delete(env.local(), set).FromJust());
   26100             : 
   26101           5 :   set->Clear();
   26102          10 :   CHECK_EQ(0U, set->Size());
   26103           5 : }
   26104             : 
   26105       23723 : TEST(SetDeleteThenAsArray) {
   26106             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26107           5 :   v8::Isolate* isolate = CcTest::isolate();
   26108           5 :   v8::HandleScope handle_scope(isolate);
   26109          10 :   LocalContext env;
   26110             : 
   26111             :   // make a Set
   26112             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
   26113             :   v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
   26114           5 :   CHECK_EQ(3U, set->Size());
   26115             : 
   26116             :   // delete the "middle" element (using AsArray to
   26117             :   // determine which element is the "middle" element)
   26118           5 :   v8::Local<v8::Array> array1 = set->AsArray();
   26119           5 :   CHECK_EQ(3U, array1->Length());
   26120          15 :   CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
   26121             :             .FromJust());
   26122             : 
   26123             :   // make sure there are no undefined values when we convert to an array again.
   26124           5 :   v8::Local<v8::Array> array2 = set->AsArray();
   26125           5 :   uint32_t length = array2->Length();
   26126           5 :   CHECK_EQ(2U, length);
   26127          10 :   for (uint32_t i = 0; i < length; i++) {
   26128          20 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26129           5 :   }
   26130           5 : }
   26131             : 
   26132       23723 : TEST(MapDeleteThenAsArray) {
   26133             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26134           5 :   v8::Isolate* isolate = CcTest::isolate();
   26135           5 :   v8::HandleScope handle_scope(isolate);
   26136          10 :   LocalContext env;
   26137             : 
   26138             :   // make a Map
   26139             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
   26140             :   v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
   26141           5 :   CHECK_EQ(3U, map->Size());
   26142             : 
   26143             :   // delete the "middle" element (using AsArray to
   26144             :   // determine which element is the "middle" element)
   26145           5 :   v8::Local<v8::Array> array1 = map->AsArray();
   26146           5 :   CHECK_EQ(6U, array1->Length());
   26147             :   // Map::AsArray returns a flat array, so the second key is at index 2.
   26148          10 :   v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
   26149          10 :   CHECK(map->Delete(env.local(), key).FromJust());
   26150             : 
   26151             :   // make sure there are no undefined values when we convert to an array again.
   26152           5 :   v8::Local<v8::Array> array2 = map->AsArray();
   26153           5 :   uint32_t length = array2->Length();
   26154           5 :   CHECK_EQ(4U, length);
   26155          20 :   for (uint32_t i = 0; i < length; i++) {
   26156          40 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26157           5 :   }
   26158           5 : }
   26159             : 
   26160       23723 : TEST(CompatibleReceiverCheckOnCachedICHandler) {
   26161           5 :   v8::Isolate* isolate = CcTest::isolate();
   26162           5 :   v8::HandleScope scope(isolate);
   26163           5 :   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
   26164           5 :   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
   26165             :   auto returns_42 =
   26166           5 :       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
   26167          15 :   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
   26168           5 :   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
   26169           5 :   child->Inherit(parent);
   26170          10 :   LocalContext env;
   26171          30 :   CHECK(env->Global()
   26172             :             ->Set(env.local(), v8_str("Child"),
   26173             :                   child->GetFunction(env.local()).ToLocalChecked())
   26174             :             .FromJust());
   26175             : 
   26176             :   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
   26177             :   CompileRun(
   26178             :       "var real = new Child();\n"
   26179             :       "for (var i = 0; i < 3; ++i) {\n"
   26180             :       "  real.age;\n"
   26181             :       "}\n");
   26182             : 
   26183             :   // Check that the cached stub is never used.
   26184             :   ExpectInt32(
   26185             :       "var fake = Object.create(Child.prototype);\n"
   26186             :       "var result = 0;\n"
   26187             :       "function test(d) {\n"
   26188             :       "  if (d == 3) return;\n"
   26189             :       "  try {\n"
   26190             :       "    fake.age;\n"
   26191             :       "    result = 1;\n"
   26192             :       "  } catch (e) {\n"
   26193             :       "  }\n"
   26194             :       "  test(d+1);\n"
   26195             :       "}\n"
   26196             :       "test(0);\n"
   26197             :       "result;\n",
   26198          10 :       0);
   26199           5 : }
   26200             : 
   26201       23724 : THREADED_TEST(ReceiverConversionForAccessors) {
   26202           6 :   LocalContext env;
   26203           6 :   v8::Isolate* isolate = CcTest::isolate();
   26204          12 :   v8::HandleScope scope(isolate);
   26205             :   Local<v8::FunctionTemplate> acc =
   26206           6 :       v8::FunctionTemplate::New(isolate, Returns42);
   26207          42 :   CHECK(env->Global()
   26208             :             ->Set(env.local(), v8_str("acc"),
   26209             :                   acc->GetFunction(env.local()).ToLocalChecked())
   26210             :             .FromJust());
   26211             : 
   26212           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   26213          12 :   templ->SetAccessorProperty(v8_str("acc"), acc, acc);
   26214           6 :   Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   26215             : 
   26216          30 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
   26217          18 :   CHECK(CompileRun("(p.acc == 42)")->BooleanValue(env.local()).FromJust());
   26218          18 :   CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   26219             : 
   26220           6 :   CHECK(!CompileRun("Number.prototype.__proto__ = p;"
   26221             :                     "var a = 1;")
   26222             :              .IsEmpty());
   26223          18 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
   26224          18 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   26225             : 
   26226           6 :   CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
   26227             :                     "var a = true;")
   26228             :              .IsEmpty());
   26229          18 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
   26230          18 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   26231             : 
   26232           6 :   CHECK(!CompileRun("String.prototype.__proto__ = p;"
   26233             :                     "var a = 'foo';")
   26234             :              .IsEmpty());
   26235          18 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
   26236          18 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
   26237             : 
   26238          18 :   CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(env.local()).FromJust());
   26239          18 :   CHECK(CompileRun("acc.call(true)==42")->BooleanValue(env.local()).FromJust());
   26240          18 :   CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(env.local()).FromJust());
   26241          18 :   CHECK(
   26242             :       CompileRun("acc.call(null) == 42")->BooleanValue(env.local()).FromJust());
   26243          18 :   CHECK(CompileRun("acc.call(undefined) == 42")
   26244             :             ->BooleanValue(env.local())
   26245           6 :             .FromJust());
   26246           6 : }
   26247             : 
   26248           5 : class FutexInterruptionThread : public v8::base::Thread {
   26249             :  public:
   26250             :   explicit FutexInterruptionThread(v8::Isolate* isolate)
   26251           5 :       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
   26252             : 
   26253           5 :   virtual void Run() {
   26254             :     // Wait a bit before terminating.
   26255           5 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   26256           5 :     isolate_->TerminateExecution();
   26257           5 :   }
   26258             : 
   26259             :  private:
   26260             :   v8::Isolate* isolate_;
   26261             : };
   26262             : 
   26263             : 
   26264       23723 : TEST(FutexInterruption) {
   26265           5 :   i::FLAG_harmony_sharedarraybuffer = true;
   26266           5 :   v8::Isolate* isolate = CcTest::isolate();
   26267           5 :   v8::HandleScope scope(isolate);
   26268          10 :   LocalContext env;
   26269             : 
   26270             :   FutexInterruptionThread timeout_thread(isolate);
   26271             : 
   26272          10 :   v8::TryCatch try_catch(CcTest::isolate());
   26273           5 :   timeout_thread.Start();
   26274             : 
   26275             :   CompileRun(
   26276             :       "var ab = new SharedArrayBuffer(4);"
   26277             :       "var i32a = new Int32Array(ab);"
   26278             :       "Atomics.wait(i32a, 0, 0);");
   26279           5 :   CHECK(try_catch.HasTerminated());
   26280          10 :   timeout_thread.Join();
   26281           5 : }
   26282             : 
   26283       23724 : THREADED_TEST(SharedArrayBuffer_AllocationInformation) {
   26284           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   26285           6 :   LocalContext env;
   26286           6 :   v8::Isolate* isolate = env->GetIsolate();
   26287          12 :   v8::HandleScope handle_scope(isolate);
   26288             : 
   26289             :   const size_t ab_size = 1024;
   26290             :   Local<v8::SharedArrayBuffer> ab =
   26291           6 :       v8::SharedArrayBuffer::New(isolate, ab_size);
   26292          12 :   ScopedSharedArrayBufferContents contents(ab->Externalize());
   26293             : 
   26294             :   // Array buffers should have normal allocation mode.
   26295           6 :   CHECK_EQ(contents.AllocationMode(),
   26296             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
   26297             :   // The allocation must contain the buffer (normally they will be equal, but
   26298             :   // this is not required by the contract).
   26299           6 :   CHECK_NOT_NULL(contents.AllocationBase());
   26300             :   const uintptr_t alloc =
   26301           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
   26302           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
   26303           6 :   CHECK_LE(alloc, data);
   26304          12 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
   26305           6 : }
   26306             : 
   26307             : static int nb_uncaught_exception_callback_calls = 0;
   26308             : 
   26309             : 
   26310           5 : bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
   26311           5 :   ++nb_uncaught_exception_callback_calls;
   26312           5 :   return false;
   26313             : }
   26314             : 
   26315             : 
   26316       23723 : TEST(AbortOnUncaughtExceptionNoAbort) {
   26317           5 :   v8::Isolate* isolate = CcTest::isolate();
   26318           5 :   v8::HandleScope handle_scope(isolate);
   26319             :   v8::Local<v8::ObjectTemplate> global_template =
   26320           5 :       v8::ObjectTemplate::New(isolate);
   26321          10 :   LocalContext env(nullptr, global_template);
   26322             : 
   26323           5 :   i::FLAG_abort_on_uncaught_exception = true;
   26324           5 :   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
   26325             : 
   26326             :   CompileRun("function boom() { throw new Error(\"boom\") }");
   26327             : 
   26328           5 :   v8::Local<v8::Object> global_object = env->Global();
   26329             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   26330          20 :       global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
   26331             : 
   26332          10 :   CHECK(foo->Call(env.local(), global_object, 0, nullptr).IsEmpty());
   26333             : 
   26334          10 :   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
   26335           5 : }
   26336             : 
   26337             : 
   26338       23723 : TEST(AccessCheckedIsConcatSpreadable) {
   26339           5 :   v8::Isolate* isolate = CcTest::isolate();
   26340           5 :   HandleScope scope(isolate);
   26341          10 :   LocalContext env;
   26342             : 
   26343             :   // Object with access check
   26344           5 :   Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
   26345           5 :   spreadable_template->SetAccessCheckCallback(AccessBlocker);
   26346             :   spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
   26347          10 :                            v8::Boolean::New(isolate, true));
   26348             :   Local<Object> object =
   26349           5 :       spreadable_template->NewInstance(env.local()).ToLocalChecked();
   26350             : 
   26351           5 :   allowed_access = true;
   26352          25 :   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   26353          15 :   object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
   26354          15 :   object->Set(env.local(), 0U, v8_str("a")).FromJust();
   26355          15 :   object->Set(env.local(), 1U, v8_str("b")).FromJust();
   26356             : 
   26357             :   // Access check is allowed, and the object is spread
   26358             :   CompileRun("var result = [].concat(object)");
   26359             :   ExpectTrue("Array.isArray(result)");
   26360           5 :   ExpectString("result[0]", "a");
   26361           5 :   ExpectString("result[1]", "b");
   26362             :   ExpectTrue("result.length === 2");
   26363             :   ExpectTrue("object[Symbol.isConcatSpreadable]");
   26364             : 
   26365             :   // If access check fails, the value of @@isConcatSpreadable is ignored
   26366           5 :   allowed_access = false;
   26367             :   CompileRun("var result = [].concat(object)");
   26368             :   ExpectTrue("Array.isArray(result)");
   26369             :   ExpectTrue("result[0] === object");
   26370             :   ExpectTrue("result.length === 1");
   26371           5 :   ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
   26372           5 : }
   26373             : 
   26374             : 
   26375       23723 : TEST(AccessCheckedToStringTag) {
   26376           5 :   v8::Isolate* isolate = CcTest::isolate();
   26377           5 :   HandleScope scope(isolate);
   26378          10 :   LocalContext env;
   26379             : 
   26380             :   // Object with access check
   26381           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26382           5 :   object_template->SetAccessCheckCallback(AccessBlocker);
   26383             :   Local<Object> object =
   26384           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26385             : 
   26386           5 :   allowed_access = true;
   26387          25 :   env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
   26388          20 :   object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
   26389          10 :       .FromJust();
   26390             : 
   26391             :   // Access check is allowed, and the toStringTag is read
   26392             :   CompileRun("var result = Object.prototype.toString.call(object)");
   26393           5 :   ExpectString("result", "[object hello]");
   26394           5 :   ExpectString("object[Symbol.toStringTag]", "hello");
   26395             : 
   26396             :   // ToString through the API should succeed too.
   26397             :   String::Utf8Value result_allowed(
   26398          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   26399           5 :   CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
   26400             : 
   26401             :   // If access check fails, the value of @@toStringTag is ignored
   26402           5 :   allowed_access = false;
   26403             :   CompileRun("var result = Object.prototype.toString.call(object)");
   26404           5 :   ExpectString("result", "[object Object]");
   26405             :   ExpectTrue("object[Symbol.toStringTag] === undefined");
   26406             : 
   26407             :   // ToString through the API should also fail.
   26408             :   String::Utf8Value result_denied(
   26409          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   26410          10 :   CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
   26411           5 : }
   26412             : 
   26413       23723 : TEST(TemplateIteratorPrototypeIntrinsics) {
   26414           5 :   v8::Isolate* isolate = CcTest::isolate();
   26415           5 :   v8::HandleScope scope(isolate);
   26416          10 :   LocalContext env;
   26417             : 
   26418             :   // Object templates.
   26419             :   {
   26420           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26421             :     object_template->SetIntrinsicDataProperty(v8_str("iter_proto"),
   26422          10 :                                               v8::kIteratorPrototype);
   26423             :     Local<Object> object =
   26424           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   26425          25 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   26426             :     ExpectTrue("obj.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   26427             :   }
   26428             :   // Setting %IteratorProto% on the function object's prototype template.
   26429             :   {
   26430           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26431          10 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   26432          15 :         v8_str("iter_proto"), v8::kIteratorPrototype);
   26433             :     Local<Function> func1 =
   26434           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26435          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   26436             :     Local<Function> func2 =
   26437           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26438          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   26439             :     ExpectTrue(
   26440             :         "func1.prototype.iter_proto === "
   26441             :         "[][Symbol.iterator]().__proto__.__proto__");
   26442             :     ExpectTrue(
   26443             :         "func2.prototype.iter_proto === "
   26444             :         "[][Symbol.iterator]().__proto__.__proto__");
   26445             :     ExpectTrue("func1.prototype.iter_proto === func2.prototype.iter_proto");
   26446             : 
   26447           5 :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   26448          25 :     CHECK(env->Global()
   26449             :               ->Set(env.local(), v8_str("instance1"), instance1)
   26450             :               .FromJust());
   26451             :     ExpectFalse("instance1.hasOwnProperty('iter_proto')");
   26452             :     ExpectTrue("'iter_proto' in instance1.__proto__");
   26453             :     ExpectTrue(
   26454             :         "instance1.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   26455             :   }
   26456             :   // Put %IteratorProto% in a function object's inheritance chain.
   26457             :   {
   26458             :     Local<FunctionTemplate> parent_template =
   26459           5 :         v8::FunctionTemplate::New(isolate);
   26460           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   26461             :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   26462          10 :                                               v8::kIteratorPrototype);
   26463           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26464           5 :     func_template->Inherit(parent_template);
   26465             : 
   26466             :     Local<Function> func =
   26467           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26468          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26469             :     ExpectTrue(
   26470             :         "func.prototype.__proto__ === "
   26471             :         "[][Symbol.iterator]().__proto__.__proto__");
   26472             : 
   26473             :     Local<Object> func_instance =
   26474           5 :         func->NewInstance(env.local()).ToLocalChecked();
   26475          25 :     CHECK(env->Global()
   26476             :               ->Set(env.local(), v8_str("instance"), func_instance)
   26477             :               .FromJust());
   26478             :     ExpectTrue(
   26479             :         "instance.__proto__.__proto__ === "
   26480             :         "[][Symbol.iterator]().__proto__.__proto__");
   26481             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   26482           5 :   }
   26483           5 : }
   26484             : 
   26485       23723 : TEST(TemplateErrorPrototypeIntrinsics) {
   26486           5 :   v8::Isolate* isolate = CcTest::isolate();
   26487           5 :   v8::HandleScope scope(isolate);
   26488          10 :   LocalContext env;
   26489             : 
   26490             :   // Object templates.
   26491             :   {
   26492           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26493             :     object_template->SetIntrinsicDataProperty(v8_str("error_proto"),
   26494          10 :                                               v8::kErrorPrototype);
   26495             :     Local<Object> object =
   26496           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   26497          25 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   26498             :     ExpectTrue("obj.error_proto === Error.prototype");
   26499           5 :     Local<Value> error = v8::Exception::Error(v8_str("error message"));
   26500          25 :     CHECK(env->Global()->Set(env.local(), v8_str("err"), error).FromJust());
   26501             :     ExpectTrue("obj.error_proto === Object.getPrototypeOf(err)");
   26502             :   }
   26503             :   // Setting %ErrorPrototype% on the function object's prototype template.
   26504             :   {
   26505           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26506          10 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   26507          15 :         v8_str("error_proto"), v8::kErrorPrototype);
   26508             :     Local<Function> func1 =
   26509           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26510          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   26511             :     Local<Function> func2 =
   26512           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26513          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   26514             :     ExpectTrue("func1.prototype.error_proto === Error.prototype");
   26515             :     ExpectTrue("func2.prototype.error_proto === Error.prototype");
   26516             :     ExpectTrue("func1.prototype.error_proto === func2.prototype.error_proto");
   26517             : 
   26518           5 :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   26519          25 :     CHECK(env->Global()
   26520             :               ->Set(env.local(), v8_str("instance1"), instance1)
   26521             :               .FromJust());
   26522             :     ExpectFalse("instance1.hasOwnProperty('error_proto')");
   26523             :     ExpectTrue("'error_proto' in instance1.__proto__");
   26524             :     ExpectTrue("instance1.error_proto === Error.prototype");
   26525             :   }
   26526             :   // Put %ErrorPrototype% in a function object's inheritance chain.
   26527             :   {
   26528             :     Local<FunctionTemplate> parent_template =
   26529           5 :         v8::FunctionTemplate::New(isolate);
   26530           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   26531             :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   26532          10 :                                               v8::kErrorPrototype);
   26533           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26534           5 :     func_template->Inherit(parent_template);
   26535             : 
   26536             :     Local<Function> func =
   26537           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26538          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26539             :     ExpectTrue("func.prototype.__proto__ === Error.prototype");
   26540             : 
   26541             :     Local<Object> func_instance =
   26542           5 :         func->NewInstance(env.local()).ToLocalChecked();
   26543          25 :     CHECK(env->Global()
   26544             :               ->Set(env.local(), v8_str("instance"), func_instance)
   26545             :               .FromJust());
   26546             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   26547             :     // Now let's check if %ErrorPrototype% properties are in the instance.
   26548             :     ExpectTrue("'constructor' in instance");
   26549             :     ExpectTrue("'message' in instance");
   26550             :     ExpectTrue("'name' in instance");
   26551             :     ExpectTrue("'toString' in instance");
   26552           5 :   }
   26553           5 : }
   26554             : 
   26555       23723 : TEST(ObjectTemplateArrayProtoIntrinsics) {
   26556           5 :   v8::Isolate* isolate = CcTest::isolate();
   26557           5 :   v8::HandleScope scope(isolate);
   26558          10 :   LocalContext env;
   26559             : 
   26560           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26561             :   object_template->SetIntrinsicDataProperty(v8_str("prop_entries"),
   26562          10 :                                             v8::kArrayProto_entries);
   26563             :   object_template->SetIntrinsicDataProperty(v8_str("prop_forEach"),
   26564          10 :                                             v8::kArrayProto_forEach);
   26565             :   object_template->SetIntrinsicDataProperty(v8_str("prop_keys"),
   26566          10 :                                             v8::kArrayProto_keys);
   26567             :   object_template->SetIntrinsicDataProperty(v8_str("prop_values"),
   26568          10 :                                             v8::kArrayProto_values);
   26569             :   Local<Object> object =
   26570           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26571          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   26572             : 
   26573             :   const struct {
   26574             :     const char* const object_property_name;
   26575             :     const char* const array_property_name;
   26576             :   } intrinsics_comparisons[] = {
   26577             :       {"prop_entries", "Array.prototype.entries"},
   26578             :       {"prop_forEach", "Array.prototype.forEach"},
   26579             :       {"prop_keys", "Array.prototype.keys"},
   26580             :       {"prop_values", "Array.prototype[Symbol.iterator]"},
   26581           5 :   };
   26582             : 
   26583          25 :   for (unsigned i = 0; i < arraysize(intrinsics_comparisons); i++) {
   26584             :     i::ScopedVector<char> test_string(64);
   26585             : 
   26586             :     i::SNPrintF(test_string, "typeof obj1.%s",
   26587          20 :                 intrinsics_comparisons[i].object_property_name);
   26588          20 :     ExpectString(test_string.start(), "function");
   26589             : 
   26590             :     i::SNPrintF(test_string, "obj1.%s === %s",
   26591             :                 intrinsics_comparisons[i].object_property_name,
   26592          20 :                 intrinsics_comparisons[i].array_property_name);
   26593             :     ExpectTrue(test_string.start());
   26594             : 
   26595             :     i::SNPrintF(test_string, "obj1.%s = 42",
   26596          20 :                 intrinsics_comparisons[i].object_property_name);
   26597             :     CompileRun(test_string.start());
   26598             : 
   26599             :     i::SNPrintF(test_string, "obj1.%s === %s",
   26600             :                 intrinsics_comparisons[i].object_property_name,
   26601          20 :                 intrinsics_comparisons[i].array_property_name);
   26602             :     ExpectFalse(test_string.start());
   26603             : 
   26604             :     i::SNPrintF(test_string, "typeof obj1.%s",
   26605          20 :                 intrinsics_comparisons[i].object_property_name);
   26606          20 :     ExpectString(test_string.start(), "number");
   26607           5 :   }
   26608           5 : }
   26609             : 
   26610       23723 : TEST(ObjectTemplatePerContextIntrinsics) {
   26611           5 :   v8::Isolate* isolate = CcTest::isolate();
   26612           5 :   v8::HandleScope scope(isolate);
   26613          10 :   LocalContext env;
   26614             : 
   26615           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26616             :   object_template->SetIntrinsicDataProperty(v8_str("values"),
   26617          10 :                                             v8::kArrayProto_values);
   26618             :   Local<Object> object =
   26619           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26620             : 
   26621          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   26622           5 :   ExpectString("typeof obj1.values", "function");
   26623             : 
   26624             :   auto values = Local<Function>::Cast(
   26625          15 :       object->Get(env.local(), v8_str("values")).ToLocalChecked());
   26626             :   auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
   26627          10 :   auto ctx = v8::Utils::OpenHandle(*env.local());
   26628          10 :   CHECK_EQ(*fn->GetCreationContext(), *ctx);
   26629             : 
   26630             :   {
   26631           5 :     LocalContext env2;
   26632             :     Local<Object> object2 =
   26633           5 :         object_template->NewInstance(env2.local()).ToLocalChecked();
   26634          25 :     CHECK(
   26635             :         env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
   26636           5 :     ExpectString("typeof obj2.values", "function");
   26637          25 :     CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
   26638             :              *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   26639             : 
   26640             :     auto values2 = Local<Function>::Cast(
   26641          15 :         object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   26642             :     auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
   26643          10 :     auto ctx2 = v8::Utils::OpenHandle(*env2.local());
   26644          10 :     CHECK_EQ(*fn2->GetCreationContext(), *ctx2);
   26645           5 :   }
   26646           5 : }
   26647             : 
   26648             : 
   26649       23723 : TEST(Proxy) {
   26650           5 :   LocalContext context;
   26651           5 :   v8::Isolate* isolate = CcTest::isolate();
   26652          10 :   v8::HandleScope scope(isolate);
   26653             :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   26654             :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   26655             : 
   26656             :   v8::Local<v8::Proxy> proxy =
   26657           5 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   26658           5 :   CHECK(proxy->IsProxy());
   26659           5 :   CHECK(!target->IsProxy());
   26660           5 :   CHECK(!proxy->IsRevoked());
   26661          10 :   CHECK(proxy->GetTarget()->SameValue(target));
   26662          10 :   CHECK(proxy->GetHandler()->SameValue(handler));
   26663             : 
   26664           5 :   proxy->Revoke();
   26665           5 :   CHECK(proxy->IsProxy());
   26666           5 :   CHECK(!target->IsProxy());
   26667           5 :   CHECK(proxy->IsRevoked());
   26668          10 :   CHECK(proxy->GetTarget()->SameValue(target));
   26669          15 :   CHECK(proxy->GetHandler()->IsNull());
   26670           5 : }
   26671             : 
   26672          10 : WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
   26673             :     v8::Isolate* isolate, WeakCallCounter* counter) {
   26674             :   v8::Locker locker(isolate);
   26675          20 :   LocalContext env;
   26676          20 :   HandleScope scope(isolate);
   26677             :   WeakCallCounterAndPersistent<Value>* val =
   26678          10 :       new WeakCallCounterAndPersistent<Value>(counter);
   26679          20 :   val->handle.Reset(isolate, Object::New(isolate));
   26680             :   val->handle.SetWeak(val, &WeakPointerCallback,
   26681             :                       v8::WeakCallbackType::kParameter);
   26682          10 :   return val;
   26683             : }
   26684             : 
   26685           5 : class MemoryPressureThread : public v8::base::Thread {
   26686             :  public:
   26687             :   explicit MemoryPressureThread(v8::Isolate* isolate,
   26688             :                                 v8::MemoryPressureLevel level)
   26689             :       : Thread(Options("MemoryPressureThread")),
   26690             :         isolate_(isolate),
   26691           5 :         level_(level) {}
   26692             : 
   26693           5 :   virtual void Run() { isolate_->MemoryPressureNotification(level_); }
   26694             : 
   26695             :  private:
   26696             :   v8::Isolate* isolate_;
   26697             :   v8::MemoryPressureLevel level_;
   26698             : };
   26699             : 
   26700       23723 : TEST(MemoryPressure) {
   26701           5 :   if (v8::internal::FLAG_optimize_for_size) return;
   26702           5 :   v8::Isolate* isolate = CcTest::isolate();
   26703             :   WeakCallCounter counter(1234);
   26704             : 
   26705             :   // Check that critical memory pressure notification sets GC interrupt.
   26706           5 :   auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   26707           5 :   CHECK(!v8::Locker::IsLocked(isolate));
   26708             :   {
   26709             :     v8::Locker locker(isolate);
   26710          10 :     v8::HandleScope scope(isolate);
   26711          10 :     LocalContext env;
   26712             :     MemoryPressureThread memory_pressure_thread(
   26713             :         isolate, v8::MemoryPressureLevel::kCritical);
   26714           5 :     memory_pressure_thread.Start();
   26715           5 :     memory_pressure_thread.Join();
   26716             :     // This should trigger GC.
   26717           5 :     CHECK_EQ(0, counter.NumberOfWeakCalls());
   26718             :     CompileRun("(function noop() { return 0; })()");
   26719          10 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   26720             :   }
   26721           5 :   delete garbage;
   26722             :   // Check that critical memory pressure notification triggers GC.
   26723           5 :   garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   26724             :   {
   26725             :     v8::Locker locker(isolate);
   26726             :     // If isolate is locked, memory pressure notification should trigger GC.
   26727           5 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   26728           5 :     isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
   26729           5 :     CHECK_EQ(2, counter.NumberOfWeakCalls());
   26730             :   }
   26731           5 :   delete garbage;
   26732             :   // Check that moderate memory pressure notification sets GC into memory
   26733             :   // optimizing mode.
   26734           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
   26735           5 :   CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   26736             :   // Check that disabling memory pressure returns GC into normal mode.
   26737           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
   26738           5 :   CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   26739             : }
   26740             : 
   26741       23723 : TEST(SetIntegrityLevel) {
   26742           5 :   LocalContext context;
   26743           5 :   v8::Isolate* isolate = CcTest::isolate();
   26744          10 :   v8::HandleScope scope(isolate);
   26745             : 
   26746           5 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   26747          25 :   CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   26748             : 
   26749             :   v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
   26750          10 :   CHECK(!is_frozen->BooleanValue(context.local()).FromJust());
   26751             : 
   26752          10 :   CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
   26753             :             .FromJust());
   26754             : 
   26755             :   is_frozen = CompileRun("Object.isFrozen(o)");
   26756          15 :   CHECK(is_frozen->BooleanValue(context.local()).FromJust());
   26757           5 : }
   26758             : 
   26759       23723 : TEST(PrivateForApiIsNumber) {
   26760           5 :   LocalContext context;
   26761           5 :   v8::Isolate* isolate = CcTest::isolate();
   26762          10 :   v8::HandleScope scope(isolate);
   26763             : 
   26764             :   // Shouldn't crash.
   26765          10 :   v8::Private::ForApi(isolate, v8_str("42"));
   26766           5 : }
   26767             : 
   26768       23724 : THREADED_TEST(ImmutableProto) {
   26769           6 :   LocalContext context;
   26770           6 :   v8::Isolate* isolate = context->GetIsolate();
   26771          12 :   v8::HandleScope handle_scope(isolate);
   26772             : 
   26773           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   26774          12 :   templ->InstanceTemplate()->SetImmutableProto();
   26775             : 
   26776           6 :   Local<v8::Object> object = templ->GetFunction(context.local())
   26777           6 :                                  .ToLocalChecked()
   26778           6 :                                  ->NewInstance(context.local())
   26779             :                                  .ToLocalChecked();
   26780             : 
   26781             :   // Look up the prototype
   26782             :   Local<v8::Value> original_proto =
   26783          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26784             : 
   26785             :   // Setting the prototype (e.g., to null) throws
   26786          12 :   CHECK(object->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   26787             : 
   26788             :   // The original prototype is still there
   26789             :   Local<Value> new_proto =
   26790          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26791           6 :   CHECK(new_proto->IsObject());
   26792          12 :   CHECK(new_proto.As<v8::Object>()
   26793             :             ->Equals(context.local(), original_proto)
   26794           6 :             .FromJust());
   26795           6 : }
   26796             : 
   26797             : Local<v8::Context> call_eval_context;
   26798             : Local<v8::Function> call_eval_bound_function;
   26799             : 
   26800          10 : static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
   26801             :   v8::Context::Scope scope(call_eval_context);
   26802             :   args.GetReturnValue().Set(
   26803             :       call_eval_bound_function
   26804          10 :           ->Call(call_eval_context, call_eval_context->Global(), 0, nullptr)
   26805           5 :           .ToLocalChecked());
   26806           5 : }
   26807             : 
   26808       23723 : TEST(CrossActivationEval) {
   26809           5 :   LocalContext env;
   26810           5 :   v8::Isolate* isolate = env->GetIsolate();
   26811          10 :   v8::HandleScope scope(isolate);
   26812             :   {
   26813           5 :     call_eval_context = v8::Context::New(isolate);
   26814             :     v8::Context::Scope scope(call_eval_context);
   26815             :     call_eval_bound_function =
   26816           5 :         Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
   26817             :   }
   26818             :   env->Global()
   26819             :       ->Set(env.local(), v8_str("CallEval"),
   26820           5 :             v8::FunctionTemplate::New(isolate, CallEval)
   26821          15 :                 ->GetFunction(env.local())
   26822          25 :                 .ToLocalChecked())
   26823          10 :       .FromJust();
   26824             :   Local<Value> result = CompileRun("CallEval();");
   26825           5 :   CHECK(result->IsInt32());
   26826          15 :   CHECK_EQ(1, result->Int32Value(env.local()).FromJust());
   26827           5 : }
   26828             : 
   26829       23723 : TEST(EvalInAccessCheckedContext) {
   26830           5 :   v8::Isolate* isolate = CcTest::isolate();
   26831           5 :   v8::HandleScope scope(isolate);
   26832             : 
   26833           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   26834             : 
   26835           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysAllowed);
   26836             : 
   26837           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   26838           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, obj_template);
   26839             : 
   26840           5 :   Local<Value> foo = v8_str("foo");
   26841           5 :   Local<Value> bar = v8_str("bar");
   26842             : 
   26843             :   // Set to different domains.
   26844           5 :   context0->SetSecurityToken(foo);
   26845           5 :   context1->SetSecurityToken(bar);
   26846             : 
   26847             :   // Set up function in context0 that uses eval from context0.
   26848           5 :   context0->Enter();
   26849             :   v8::Local<v8::Value> fun = CompileRun(
   26850             :       "var x = 42;"
   26851             :       "(function() {"
   26852             :       "  var e = eval;"
   26853             :       "  return function(s) { return e(s); }"
   26854           5 :       "})()");
   26855           5 :   context0->Exit();
   26856             : 
   26857             :   // Put the function into context1 and call it. Since the access check
   26858             :   // callback always returns true, the call succeeds even though the tokens
   26859             :   // are different.
   26860           5 :   context1->Enter();
   26861          20 :   context1->Global()->Set(context1, v8_str("fun"), fun).FromJust();
   26862             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   26863          10 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   26864           5 :   context1->Exit();
   26865           5 : }
   26866             : 
   26867       23724 : THREADED_TEST(ImmutableProtoWithParent) {
   26868           6 :   LocalContext context;
   26869           6 :   v8::Isolate* isolate = context->GetIsolate();
   26870          12 :   v8::HandleScope handle_scope(isolate);
   26871             : 
   26872           6 :   Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate);
   26873             : 
   26874           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   26875           6 :   templ->Inherit(parent);
   26876          12 :   templ->PrototypeTemplate()->SetImmutableProto();
   26877             : 
   26878             :   Local<v8::Function> function =
   26879           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   26880             :   Local<v8::Object> instance =
   26881           6 :       function->NewInstance(context.local()).ToLocalChecked();
   26882             :   Local<v8::Object> prototype =
   26883          18 :       instance->Get(context.local(), v8_str("__proto__"))
   26884           6 :           .ToLocalChecked()
   26885           6 :           ->ToObject(context.local())
   26886           6 :           .ToLocalChecked();
   26887             : 
   26888             :   // Look up the prototype
   26889             :   Local<v8::Value> original_proto =
   26890          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26891             : 
   26892             :   // Setting the prototype (e.g., to null) throws
   26893          12 :   CHECK(
   26894             :       prototype->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   26895             : 
   26896             :   // The original prototype is still there
   26897             :   Local<Value> new_proto =
   26898          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26899           6 :   CHECK(new_proto->IsObject());
   26900          12 :   CHECK(new_proto.As<v8::Object>()
   26901             :             ->Equals(context.local(), original_proto)
   26902           6 :             .FromJust());
   26903           6 : }
   26904             : 
   26905       23723 : TEST(InternalFieldsOnGlobalProxy) {
   26906           5 :   v8::Isolate* isolate = CcTest::isolate();
   26907           5 :   v8::HandleScope scope(isolate);
   26908             : 
   26909           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   26910           5 :   obj_template->SetInternalFieldCount(1);
   26911             : 
   26912           5 :   v8::Local<v8::Context> context = Context::New(isolate, nullptr, obj_template);
   26913           5 :   v8::Local<v8::Object> global = context->Global();
   26914           5 :   CHECK_EQ(1, global->InternalFieldCount());
   26915           5 : }
   26916             : 
   26917       23724 : THREADED_TEST(ImmutableProtoGlobal) {
   26918           6 :   v8::Isolate* isolate = CcTest::isolate();
   26919           6 :   v8::HandleScope handle_scope(isolate);
   26920           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   26921           6 :   global_template->SetImmutableProto();
   26922           6 :   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   26923             :   Context::Scope context_scope(context);
   26924             :   v8::Local<Value> result = CompileRun(
   26925             :       "global = this;"
   26926             :       "(function() {"
   26927             :       "  try {"
   26928             :       "    global.__proto__ = {};"
   26929             :       "    return 0;"
   26930             :       "  } catch (e) {"
   26931             :       "    return 1;"
   26932             :       "  }"
   26933             :       "})()");
   26934          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 1))
   26935           6 :             .FromJust());
   26936           6 : }
   26937             : 
   26938       23724 : THREADED_TEST(MutableProtoGlobal) {
   26939           6 :   v8::Isolate* isolate = CcTest::isolate();
   26940           6 :   v8::HandleScope handle_scope(isolate);
   26941           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   26942           6 :   v8::Local<Context> context = Context::New(isolate, 0, global_template);
   26943             :   Context::Scope context_scope(context);
   26944             :   v8::Local<Value> result = CompileRun(
   26945             :       "global = this;"
   26946             :       "(function() {"
   26947             :       "  try {"
   26948             :       "    global.__proto__ = {};"
   26949             :       "    return 0;"
   26950             :       "  } catch (e) {"
   26951             :       "    return 1;"
   26952             :       "  }"
   26953             :       "})()");
   26954          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 0))
   26955           6 :             .FromJust());
   26956           6 : }
   26957             : 
   26958       23723 : TEST(InternalFieldsOnTypedArray) {
   26959           5 :   LocalContext env;
   26960           5 :   v8::Isolate* isolate = env->GetIsolate();
   26961          10 :   v8::HandleScope scope(isolate);
   26962           5 :   v8::Local<v8::Context> context = env.local();
   26963             :   Context::Scope context_scope(context);
   26964           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   26965           5 :   v8::Local<v8::Uint8Array> array = v8::Uint8Array::New(buffer, 0, 1);
   26966          15 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   26967          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   26968             :              array->GetAlignedPointerFromInternalField(i));
   26969           5 :   }
   26970           5 : }
   26971             : 
   26972       23723 : TEST(InternalFieldsOnDataView) {
   26973           5 :   LocalContext env;
   26974           5 :   v8::Isolate* isolate = env->GetIsolate();
   26975          10 :   v8::HandleScope scope(isolate);
   26976           5 :   v8::Local<v8::Context> context = env.local();
   26977             :   Context::Scope context_scope(context);
   26978           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   26979           5 :   v8::Local<v8::DataView> array = v8::DataView::New(buffer, 0, 1);
   26980          15 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   26981          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   26982             :              array->GetAlignedPointerFromInternalField(i));
   26983           5 :   }
   26984           5 : }
   26985             : 
   26986       23723 : TEST(SetPrototypeTemplate) {
   26987           5 :   LocalContext env;
   26988           5 :   v8::Isolate* isolate = env->GetIsolate();
   26989          10 :   v8::HandleScope scope(isolate);
   26990             : 
   26991           5 :   Local<FunctionTemplate> HTMLElementTemplate = FunctionTemplate::New(isolate);
   26992             :   Local<FunctionTemplate> HTMLImageElementTemplate =
   26993           5 :       FunctionTemplate::New(isolate);
   26994           5 :   HTMLImageElementTemplate->Inherit(HTMLElementTemplate);
   26995             : 
   26996           5 :   Local<FunctionTemplate> ImageTemplate = FunctionTemplate::New(isolate);
   26997           5 :   ImageTemplate->SetPrototypeProviderTemplate(HTMLImageElementTemplate);
   26998             : 
   26999             :   Local<Function> HTMLImageElement =
   27000           5 :       HTMLImageElementTemplate->GetFunction(env.local()).ToLocalChecked();
   27001             :   Local<Function> Image =
   27002           5 :       ImageTemplate->GetFunction(env.local()).ToLocalChecked();
   27003             : 
   27004          25 :   CHECK(env->Global()
   27005             :             ->Set(env.local(), v8_str("HTMLImageElement"), HTMLImageElement)
   27006             :             .FromJust());
   27007          25 :   CHECK(env->Global()->Set(env.local(), v8_str("Image"), Image).FromJust());
   27008             : 
   27009           5 :   ExpectTrue("Image.prototype === HTMLImageElement.prototype");
   27010           5 : }
   27011             : 
   27012         120 : void ensure_receiver_is_global_proxy(
   27013             :     v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
   27014         120 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSGlobalProxy());
   27015         120 : }
   27016             : 
   27017       23724 : THREADED_TEST(GlobalAccessorInfo) {
   27018           6 :   v8::Isolate* isolate = CcTest::isolate();
   27019           6 :   v8::HandleScope scope(isolate);
   27020           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   27021             :   global_template->SetAccessor(
   27022             :       v8::String::NewFromUtf8(isolate, "prop", v8::NewStringType::kInternalized)
   27023             :           .ToLocalChecked(),
   27024          12 :       &ensure_receiver_is_global_proxy);
   27025          12 :   LocalContext env(nullptr, global_template);
   27026             :   CompileRun("for (var i = 0; i < 10; i++) this.prop");
   27027           6 :   CompileRun("for (var i = 0; i < 10; i++) prop");
   27028           6 : }
   27029             : 
   27030       23723 : UNINITIALIZED_TEST(IncreaseHeapLimitForDebugging) {
   27031             :   v8::Isolate::CreateParams create_params;
   27032             :   create_params.constraints.set_max_old_space_size(16);
   27033           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   27034           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   27035             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27036             :   {
   27037           5 :     size_t limit_before = i_isolate->heap()->MaxOldGenerationSize();
   27038           5 :     CHECK_EQ(16 * i::MB, limit_before);
   27039           5 :     CHECK(!isolate->IsHeapLimitIncreasedForDebugging());
   27040           5 :     isolate->IncreaseHeapLimitForDebugging();
   27041           5 :     CHECK(isolate->IsHeapLimitIncreasedForDebugging());
   27042           5 :     size_t limit_after = i_isolate->heap()->MaxOldGenerationSize();
   27043           5 :     CHECK_EQ(4 * 16 * i::MB, limit_after);
   27044           5 :     isolate->RestoreOriginalHeapLimit();
   27045           5 :     CHECK(!isolate->IsHeapLimitIncreasedForDebugging());
   27046           5 :     CHECK_EQ(limit_before, i_isolate->heap()->MaxOldGenerationSize());
   27047             :   }
   27048           5 :   isolate->Dispose();
   27049           5 : }
   27050             : 
   27051       23723 : TEST(DeterministicRandomNumberGeneration) {
   27052           5 :   v8::HandleScope scope(CcTest::isolate());
   27053             : 
   27054           5 :   int previous_seed = v8::internal::FLAG_random_seed;
   27055           5 :   v8::internal::FLAG_random_seed = 1234;
   27056             : 
   27057             :   double first_value;
   27058             :   double second_value;
   27059             :   {
   27060           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27061             :     Context::Scope context_scope(context);
   27062             :     v8::Local<Value> result = CompileRun("Math.random();");
   27063          10 :     first_value = result->ToNumber(context).ToLocalChecked()->Value();
   27064             :   }
   27065             :   {
   27066           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27067             :     Context::Scope context_scope(context);
   27068             :     v8::Local<Value> result = CompileRun("Math.random();");
   27069          10 :     second_value = result->ToNumber(context).ToLocalChecked()->Value();
   27070             :   }
   27071           5 :   CHECK_EQ(first_value, second_value);
   27072             : 
   27073           5 :   v8::internal::FLAG_random_seed = previous_seed;
   27074           5 : }
   27075             : 
   27076       23723 : UNINITIALIZED_TEST(AllowAtomicsWait) {
   27077             :   v8::Isolate::CreateParams create_params;
   27078           5 :   create_params.allow_atomics_wait = false;
   27079           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   27080           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   27081          10 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27082             :   {
   27083           5 :     CHECK_EQ(false, i_isolate->allow_atomics_wait());
   27084           5 :     isolate->SetAllowAtomicsWait(true);
   27085           5 :     CHECK_EQ(true, i_isolate->allow_atomics_wait());
   27086             :   }
   27087           5 :   isolate->Dispose();
   27088           5 : }
   27089             : 
   27090             : enum ContextId { EnteredContext, CurrentContext };
   27091             : 
   27092          20 : void CheckContexts(v8::Isolate* isolate) {
   27093          60 :   CHECK_EQ(CurrentContext, isolate->GetCurrentContext()
   27094             :                                ->GetEmbedderData(1)
   27095             :                                .As<v8::Integer>()
   27096             :                                ->Value());
   27097          60 :   CHECK_EQ(EnteredContext, isolate->GetEnteredContext()
   27098             :                                ->GetEmbedderData(1)
   27099             :                                .As<v8::Integer>()
   27100             :                                ->Value());
   27101          20 : }
   27102             : 
   27103           5 : void ContextCheckGetter(Local<String> name,
   27104             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   27105           5 :   CheckContexts(info.GetIsolate());
   27106             :   info.GetReturnValue().Set(true);
   27107           5 : }
   27108             : 
   27109           5 : void ContextCheckSetter(Local<String> name, Local<Value>,
   27110             :                         const v8::PropertyCallbackInfo<void>& info) {
   27111           5 :   CheckContexts(info.GetIsolate());
   27112           5 : }
   27113             : 
   27114          20 : void ContextCheckToString(const v8::FunctionCallbackInfo<v8::Value>& info) {
   27115          10 :   CheckContexts(info.GetIsolate());
   27116          10 :   info.GetReturnValue().Set(v8_str("foo"));
   27117          10 : }
   27118             : 
   27119       23723 : TEST(CorrectEnteredContext) {
   27120           5 :   v8::HandleScope scope(CcTest::isolate());
   27121             : 
   27122          10 :   LocalContext currentContext;
   27123             :   currentContext->SetEmbedderData(
   27124          10 :       1, v8::Integer::New(currentContext->GetIsolate(), CurrentContext));
   27125          10 :   LocalContext enteredContext;
   27126             :   enteredContext->SetEmbedderData(
   27127          10 :       1, v8::Integer::New(enteredContext->GetIsolate(), EnteredContext));
   27128             : 
   27129           5 :   v8::Context::Scope contextScope(enteredContext.local());
   27130             : 
   27131             :   v8::Local<v8::ObjectTemplate> object_template =
   27132           5 :       ObjectTemplate::New(currentContext->GetIsolate());
   27133             :   object_template->SetAccessor(v8_str("p"), &ContextCheckGetter,
   27134           5 :                                &ContextCheckSetter);
   27135             : 
   27136             :   v8::Local<v8::Object> object =
   27137           5 :       object_template->NewInstance(currentContext.local()).ToLocalChecked();
   27138             : 
   27139          15 :   object->Get(currentContext.local(), v8_str("p")).ToLocalChecked();
   27140          15 :   object->Set(currentContext.local(), v8_str("p"), v8_int(0)).FromJust();
   27141             : 
   27142             :   v8::Local<v8::Function> to_string =
   27143          10 :       v8::Function::New(currentContext.local(), ContextCheckToString)
   27144           5 :           .ToLocalChecked();
   27145             : 
   27146          10 :   to_string->Call(currentContext.local(), object, 0, nullptr).ToLocalChecked();
   27147             : 
   27148             :   object
   27149             :       ->CreateDataProperty(currentContext.local(), v8_str("toString"),
   27150          15 :                            to_string)
   27151          10 :       .FromJust();
   27152             : 
   27153          10 :   object->ToString(currentContext.local()).ToLocalChecked();
   27154           5 : }
   27155             : 
   27156           5 : v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallbackResolve(
   27157             :     Local<Context> context, Local<v8::ScriptOrModule> referrer,
   27158             :     Local<String> specifier) {
   27159           5 :   CHECK(!referrer.IsEmpty());
   27160             :   String::Utf8Value referrer_utf8(
   27161          10 :       context->GetIsolate(), Local<String>::Cast(referrer->GetResourceName()));
   27162           5 :   CHECK_EQ(0, strcmp("www.google.com", *referrer_utf8));
   27163          15 :   CHECK(referrer->GetHostDefinedOptions()->Get(0)->IsSymbol());
   27164             : 
   27165           5 :   CHECK(!specifier.IsEmpty());
   27166          10 :   String::Utf8Value specifier_utf8(context->GetIsolate(), specifier);
   27167           5 :   CHECK_EQ(0, strcmp("index.js", *specifier_utf8));
   27168             : 
   27169             :   Local<v8::Promise::Resolver> resolver =
   27170           5 :       v8::Promise::Resolver::New(context).ToLocalChecked();
   27171           5 :   auto result = v8_str("hello world");
   27172          10 :   resolver->Resolve(context, result).ToChecked();
   27173          10 :   return resolver->GetPromise();
   27174             : }
   27175             : 
   27176       23723 : TEST(DynamicImport) {
   27177           5 :   i::FLAG_harmony_dynamic_import = true;
   27178           5 :   LocalContext context;
   27179           5 :   v8::Isolate* isolate = context->GetIsolate();
   27180          10 :   v8::HandleScope scope(isolate);
   27181             : 
   27182             :   isolate->SetHostImportModuleDynamicallyCallback(
   27183           5 :       HostImportModuleDynamicallyCallbackResolve);
   27184             : 
   27185          10 :   i::Handle<i::String> url(v8::Utils::OpenHandle(*v8_str("www.google.com")));
   27186          10 :   i::Handle<i::Object> specifier(v8::Utils::OpenHandle(*v8_str("index.js")));
   27187          10 :   i::Handle<i::String> result(v8::Utils::OpenHandle(*v8_str("hello world")));
   27188          10 :   i::Handle<i::String> source(v8::Utils::OpenHandle(*v8_str("foo")));
   27189             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27190           5 :   i::Handle<i::FixedArray> options = i_isolate->factory()->NewFixedArray(1);
   27191           5 :   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewSymbol();
   27192           5 :   options->set(0, *symbol);
   27193           5 :   i::Handle<i::Script> referrer = i_isolate->factory()->NewScript(source);
   27194           5 :   referrer->set_name(*url);
   27195           5 :   referrer->set_host_defined_options(*options);
   27196             :   i::MaybeHandle<i::JSPromise> maybe_promise =
   27197           5 :       i_isolate->RunHostImportModuleDynamicallyCallback(referrer, specifier);
   27198             :   i::Handle<i::JSPromise> promise = maybe_promise.ToHandleChecked();
   27199           5 :   isolate->RunMicrotasks();
   27200          10 :   CHECK(result->Equals(i::String::cast(promise->result())));
   27201           5 : }
   27202             : 
   27203           5 : void HostInitializeImportMetaObjectCallbackStatic(Local<Context> context,
   27204             :                                                   Local<Module> module,
   27205             :                                                   Local<Object> meta) {
   27206           5 :   CHECK(!module.IsEmpty());
   27207             : 
   27208          20 :   meta->CreateDataProperty(context, v8_str("foo"), v8_str("bar")).ToChecked();
   27209           5 : }
   27210             : 
   27211           0 : v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
   27212             :                                                        Local<String> specifier,
   27213             :                                                        Local<Module> referrer) {
   27214           0 :   CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
   27215             : }
   27216             : 
   27217       23723 : TEST(ImportMeta) {
   27218           5 :   i::FLAG_harmony_dynamic_import = true;
   27219           5 :   i::FLAG_harmony_import_meta = true;
   27220           5 :   LocalContext context;
   27221           5 :   v8::Isolate* isolate = context->GetIsolate();
   27222          10 :   v8::HandleScope scope(isolate);
   27223             : 
   27224             :   isolate->SetHostInitializeImportMetaObjectCallback(
   27225           5 :       HostInitializeImportMetaObjectCallbackStatic);
   27226             : 
   27227             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27228           5 :   Local<String> url = v8_str("www.google.com");
   27229           5 :   Local<String> source_text = v8_str("import.meta;");
   27230             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27231             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27232             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27233             :                           Local<v8::Boolean>(), True(isolate));
   27234             :   v8::ScriptCompiler::Source source(source_text, origin);
   27235             :   Local<Module> module =
   27236           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27237             :   i::Handle<i::Object> meta =
   27238             :       i_isolate->RunHostInitializeImportMetaObjectCallback(
   27239           5 :           v8::Utils::OpenHandle(*module));
   27240           5 :   CHECK(meta->IsJSObject());
   27241             :   Local<Object> meta_obj = Local<Object>::Cast(v8::Utils::ToLocal(meta));
   27242          15 :   CHECK(meta_obj->Get(context.local(), v8_str("foo"))
   27243             :             .ToLocalChecked()
   27244             :             ->IsString());
   27245          15 :   CHECK(meta_obj->Get(context.local(), v8_str("zapp"))
   27246             :             .ToLocalChecked()
   27247             :             ->IsUndefined());
   27248             : 
   27249           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27250          10 :       .ToChecked();
   27251           5 :   Local<Value> result = module->Evaluate(context.local()).ToLocalChecked();
   27252          10 :   CHECK(result->StrictEquals(Local<v8::Value>::Cast(v8::Utils::ToLocal(meta))));
   27253           5 : }
   27254             : 
   27255       23723 : TEST(GlobalTemplateWithDoubleProperty) {
   27256           5 :   v8::Isolate* isolate = CcTest::isolate();
   27257           5 :   v8::HandleScope handle_scope(isolate);
   27258             : 
   27259           5 :   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   27260          15 :   global->Set(v8_str("double"), v8_num(3.14));
   27261             : 
   27262           5 :   v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
   27263             : 
   27264             :   v8::Context::Scope context_scope(context);
   27265             : 
   27266             :   Local<Value> result = CompileRun("double");
   27267           5 :   CHECK(result->IsNumber());
   27268          15 :   CheckDoubleEquals(3.14, result->NumberValue(context).ToChecked());
   27269           5 : }
   27270             : 
   27271       23723 : TEST(PrimitiveArray) {
   27272           5 :   v8::Isolate* isolate = CcTest::isolate();
   27273           5 :   v8::HandleScope scope(isolate);
   27274          10 :   LocalContext env;
   27275             : 
   27276             :   int length = 5;
   27277           5 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 5));
   27278           5 :   CHECK_EQ(length, array->Length());
   27279             : 
   27280          25 :   for (int i = 0; i < length; i++) {
   27281          25 :     Local<v8::Primitive> item = array->Get(i);
   27282          25 :     CHECK(item->IsUndefined());
   27283             :   }
   27284             : 
   27285           5 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   27286           5 :   array->Set(0, symbol);
   27287          10 :   CHECK(array->Get(0)->IsSymbol());
   27288             : 
   27289             :   Local<v8::String> string =
   27290             :       v8::String::NewFromUtf8(isolate, "test", v8::NewStringType::kInternalized)
   27291           5 :           .ToLocalChecked();
   27292           5 :   array->Set(1, string);
   27293          10 :   CHECK(array->Get(0)->IsSymbol());
   27294          10 :   CHECK(array->Get(1)->IsString());
   27295             : 
   27296           5 :   Local<v8::Number> num = v8::Number::New(env->GetIsolate(), 3.1415926);
   27297           5 :   array->Set(2, num);
   27298          10 :   CHECK(array->Get(0)->IsSymbol());
   27299          10 :   CHECK(array->Get(1)->IsString());
   27300          10 :   CHECK(array->Get(2)->IsNumber());
   27301             : 
   27302             :   v8::Local<v8::Boolean> f = v8::False(isolate);
   27303           5 :   array->Set(3, f);
   27304          10 :   CHECK(array->Get(0)->IsSymbol());
   27305          10 :   CHECK(array->Get(1)->IsString());
   27306          10 :   CHECK(array->Get(2)->IsNumber());
   27307          10 :   CHECK(array->Get(3)->IsBoolean());
   27308             : 
   27309           5 :   v8::Local<v8::Primitive> n = v8::Null(isolate);
   27310           5 :   array->Set(4, n);
   27311          10 :   CHECK(array->Get(0)->IsSymbol());
   27312          10 :   CHECK(array->Get(1)->IsString());
   27313          10 :   CHECK(array->Get(2)->IsNumber());
   27314          10 :   CHECK(array->Get(3)->IsBoolean());
   27315          15 :   CHECK(array->Get(4)->IsNull());
   27316           5 : }
   27317             : 
   27318       23723 : TEST(PersistentValueMap) {
   27319           5 :   v8::Isolate* isolate = CcTest::isolate();
   27320           5 :   v8::HandleScope scope(isolate);
   27321          10 :   LocalContext env;
   27322             : 
   27323             :   v8::PersistentValueMap<
   27324             :       std::string, v8::Value,
   27325             :       v8::DefaultPersistentValueMapTraits<std::string, v8::Value>>
   27326             :       map(isolate);
   27327             :   v8::Local<v8::Value> value =
   27328             :       v8::String::NewFromUtf8(isolate, "value",
   27329             :                               v8::NewStringType::kInternalized)
   27330           5 :           .ToLocalChecked();
   27331          20 :   map.Set("key", value);
   27332       71159 : }

Generated by: LCOV version 1.10