LCOV - code coverage report
Current view: top level - test/cctest - test-api.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 14056 14139 99.4 %
Date: 2019-01-20 Functions: 1120 1189 94.2 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include <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-inl.h"
      42             : #include "src/arguments.h"
      43             : #include "src/base/overflowing-math.h"
      44             : #include "src/base/platform/platform.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/global-handles.h"
      50             : #include "src/heap/incremental-marking.h"
      51             : #include "src/heap/local-allocator.h"
      52             : #include "src/lookup.h"
      53             : #include "src/objects-inl.h"
      54             : #include "src/objects/hash-table-inl.h"
      55             : #include "src/objects/js-array-buffer-inl.h"
      56             : #include "src/objects/js-array-inl.h"
      57             : #include "src/objects/js-promise-inl.h"
      58             : #include "src/profiler/cpu-profiler.h"
      59             : #include "src/unicode-inl.h"
      60             : #include "src/utils.h"
      61             : #include "src/vm-state.h"
      62             : #include "src/wasm/wasm-js.h"
      63             : #include "test/cctest/heap/heap-tester.h"
      64             : #include "test/cctest/heap/heap-utils.h"
      65             : 
      66             : static const bool kLogThreading = false;
      67             : 
      68             : using ::v8::Array;
      69             : using ::v8::Boolean;
      70             : using ::v8::BooleanObject;
      71             : using ::v8::Context;
      72             : using ::v8::Extension;
      73             : using ::v8::Function;
      74             : using ::v8::FunctionTemplate;
      75             : using ::v8::HandleScope;
      76             : using ::v8::Local;
      77             : using ::v8::Maybe;
      78             : using ::v8::Message;
      79             : using ::v8::MessageCallback;
      80             : using ::v8::Module;
      81             : using ::v8::Name;
      82             : using ::v8::None;
      83             : using ::v8::Object;
      84             : using ::v8::ObjectTemplate;
      85             : using ::v8::Persistent;
      86             : using ::v8::PropertyAttribute;
      87             : using ::v8::Script;
      88             : using ::v8::StackTrace;
      89             : using ::v8::String;
      90             : using ::v8::Symbol;
      91             : using ::v8::TryCatch;
      92             : using ::v8::Undefined;
      93             : using ::v8::V8;
      94             : using ::v8::Value;
      95             : 
      96             : 
      97             : #define THREADED_PROFILED_TEST(Name)                                 \
      98             :   static void Test##Name();                                          \
      99             :   TEST(Name##WithProfiler) {                                         \
     100             :     RunWithProfiler(&Test##Name);                                    \
     101             :   }                                                                  \
     102             :   THREADED_TEST(Name)
     103             : 
     104          75 : void RunWithProfiler(void (*test)()) {
     105          75 :   LocalContext env;
     106         150 :   v8::HandleScope scope(env->GetIsolate());
     107          75 :   v8::Local<v8::String> profile_name = v8_str("my_profile1");
     108          75 :   v8::CpuProfiler* cpu_profiler = v8::CpuProfiler::New(env->GetIsolate());
     109          75 :   cpu_profiler->StartProfiling(profile_name);
     110          75 :   (*test)();
     111          75 :   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
     112         150 :   cpu_profiler->Dispose();
     113          75 : }
     114             : 
     115             : 
     116             : static int signature_callback_count;
     117             : static Local<Value> signature_expected_receiver;
     118        3900 : static void IncrementingSignatureCallback(
     119       28080 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     120        3900 :   ApiTestFuzzer::Fuzz();
     121        3900 :   signature_callback_count++;
     122       11700 :   CHECK(signature_expected_receiver->Equals(
     123             :                                        args.GetIsolate()->GetCurrentContext(),
     124             :                                        args.Holder())
     125             :             .FromJust());
     126       11700 :   CHECK(signature_expected_receiver->Equals(
     127             :                                        args.GetIsolate()->GetCurrentContext(),
     128             :                                        args.This())
     129             :             .FromJust());
     130             :   v8::Local<v8::Array> result =
     131        3900 :       v8::Array::New(args.GetIsolate(), args.Length());
     132       10920 :   for (int i = 0; i < args.Length(); i++) {
     133        6240 :     CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
     134             :                       v8::Integer::New(args.GetIsolate(), i), args[i])
     135             :               .FromJust());
     136             :   }
     137             :   args.GetReturnValue().Set(result);
     138        3900 : }
     139             : 
     140             : 
     141         215 : static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
     142             :   info.GetReturnValue().Set(42);
     143         215 : }
     144             : 
     145             : 
     146             : // Tests that call v8::V8::Dispose() cannot be threaded.
     147       28342 : UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
     148           5 :   CHECK(v8::V8::Initialize());
     149           5 :   CHECK(v8::V8::Dispose());
     150           5 : }
     151             : 
     152             : 
     153             : // Tests that call v8::V8::Dispose() cannot be threaded.
     154       28342 : UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
     155           5 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     156          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     157          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     158          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     159          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     160           5 : }
     161             : 
     162             : // Tests that Smi::kZero is set up properly.
     163       28347 : UNINITIALIZED_TEST(SmiZero) { CHECK_EQ(i::Smi::kZero, i::Smi::kZero); }
     164             : 
     165       28343 : THREADED_TEST(Handles) {
     166           6 :   v8::HandleScope scope(CcTest::isolate());
     167             :   Local<Context> local_env;
     168             :   {
     169           6 :     LocalContext env;
     170           6 :     local_env = env.local();
     171             :   }
     172             : 
     173             :   // Local context should still be live.
     174           6 :   CHECK(!local_env.IsEmpty());
     175           6 :   local_env->Enter();
     176             : 
     177           6 :   v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
     178           6 :   CHECK(!undef.IsEmpty());
     179           6 :   CHECK(undef->IsUndefined());
     180             : 
     181             :   const char* source = "1 + 2 + 3";
     182           6 :   Local<Script> script = v8_compile(source);
     183           6 :   CHECK_EQ(6, v8_run_int32value(script));
     184             : 
     185           6 :   local_env->Exit();
     186           6 : }
     187             : 
     188             : 
     189       28343 : THREADED_TEST(IsolateOfContext) {
     190           6 :   v8::HandleScope scope(CcTest::isolate());
     191           6 :   v8::Local<Context> env = Context::New(CcTest::isolate());
     192             : 
     193           6 :   CHECK(!env->GetIsolate()->InContext());
     194           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     195           6 :   env->Enter();
     196           6 :   CHECK(env->GetIsolate()->InContext());
     197           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     198           6 :   env->Exit();
     199           6 :   CHECK(!env->GetIsolate()->InContext());
     200           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     201           6 : }
     202             : 
     203         420 : static void TestSignatureLooped(const char* operation, Local<Value> receiver,
     204             :                                 v8::Isolate* isolate) {
     205             :   i::ScopedVector<char> source(200);
     206             :   i::SNPrintF(source,
     207             :               "for (var i = 0; i < 10; i++) {"
     208             :               "  %s"
     209             :               "}",
     210         420 :               operation);
     211         420 :   signature_callback_count = 0;
     212         420 :   signature_expected_receiver = receiver;
     213             :   bool expected_to_throw = receiver.IsEmpty();
     214         840 :   v8::TryCatch try_catch(isolate);
     215             :   CompileRun(source.start());
     216         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     217         420 :   if (!expected_to_throw) {
     218         300 :     CHECK_EQ(10, signature_callback_count);
     219             :   } else {
     220         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     221             :               ->Equals(isolate->GetCurrentContext(),
     222             :                        try_catch.Exception()
     223             :                            ->ToString(isolate->GetCurrentContext())
     224             :                            .ToLocalChecked())
     225             :               .FromJust());
     226             :   }
     227         420 : }
     228             : 
     229         420 : static void TestSignatureOptimized(const char* operation, Local<Value> receiver,
     230             :                                    v8::Isolate* isolate) {
     231             :   i::ScopedVector<char> source(200);
     232             :   i::SNPrintF(source,
     233             :               "function test() {"
     234             :               "  %s"
     235             :               "}"
     236             :               "try { test() } catch(e) {}"
     237             :               "try { test() } catch(e) {}"
     238             :               "%%OptimizeFunctionOnNextCall(test);"
     239             :               "test()",
     240         420 :               operation);
     241         420 :   signature_callback_count = 0;
     242         420 :   signature_expected_receiver = receiver;
     243             :   bool expected_to_throw = receiver.IsEmpty();
     244         840 :   v8::TryCatch try_catch(isolate);
     245             :   CompileRun(source.start());
     246         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     247         420 :   if (!expected_to_throw) {
     248         300 :     CHECK_EQ(3, signature_callback_count);
     249             :   } else {
     250         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     251             :               ->Equals(isolate->GetCurrentContext(),
     252             :                        try_catch.Exception()
     253             :                            ->ToString(isolate->GetCurrentContext())
     254             :                            .ToLocalChecked())
     255             :               .FromJust());
     256             :   }
     257         420 : }
     258             : 
     259         420 : static void TestSignature(const char* operation, Local<Value> receiver,
     260             :                           v8::Isolate* isolate) {
     261         420 :   TestSignatureLooped(operation, receiver, isolate);
     262         420 :   TestSignatureOptimized(operation, receiver, isolate);
     263         420 : }
     264             : 
     265       28343 : THREADED_TEST(ReceiverSignature) {
     266           6 :   i::FLAG_allow_natives_syntax = true;
     267           6 :   LocalContext env;
     268           6 :   v8::Isolate* isolate = env->GetIsolate();
     269          12 :   v8::HandleScope scope(isolate);
     270             :   // Setup templates.
     271           6 :   v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
     272           6 :   v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
     273             :   v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
     274           6 :       isolate, IncrementingSignatureCallback, Local<Value>(), sig);
     275             :   v8::Local<v8::FunctionTemplate> callback =
     276           6 :       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
     277           6 :   v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
     278           6 :   sub_fun->Inherit(fun);
     279             :   v8::Local<v8::FunctionTemplate> direct_sub_fun =
     280           6 :       v8::FunctionTemplate::New(isolate);
     281           6 :   direct_sub_fun->Inherit(fun);
     282             :   v8::Local<v8::FunctionTemplate> unrel_fun =
     283           6 :       v8::FunctionTemplate::New(isolate);
     284             :   // Install properties.
     285           6 :   v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
     286          12 :   fun_proto->Set(v8_str("prop_sig"), callback_sig);
     287          12 :   fun_proto->Set(v8_str("prop"), callback);
     288             :   fun_proto->SetAccessorProperty(
     289          12 :       v8_str("accessor_sig"), callback_sig, callback_sig);
     290          12 :   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
     291             :   // Instantiate templates.
     292             :   Local<Value> fun_instance =
     293          18 :       fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     294             :   Local<Value> sub_fun_instance =
     295          18 :       sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     296             :   // Instance template with properties.
     297             :   v8::Local<v8::ObjectTemplate> direct_instance_templ =
     298           6 :       direct_sub_fun->InstanceTemplate();
     299          12 :   direct_instance_templ->Set(v8_str("prop_sig"), callback_sig);
     300          12 :   direct_instance_templ->Set(v8_str("prop"), callback);
     301             :   direct_instance_templ->SetAccessorProperty(v8_str("accessor_sig"),
     302          12 :                                              callback_sig, callback_sig);
     303             :   direct_instance_templ->SetAccessorProperty(v8_str("accessor"), callback,
     304          12 :                                              callback);
     305             :   Local<Value> direct_instance =
     306           6 :       direct_instance_templ->NewInstance(env.local()).ToLocalChecked();
     307             :   // Setup global variables.
     308          36 :   CHECK(env->Global()
     309             :             ->Set(env.local(), v8_str("Fun"),
     310             :                   fun->GetFunction(env.local()).ToLocalChecked())
     311             :             .FromJust());
     312          42 :   CHECK(env->Global()
     313             :             ->Set(env.local(), v8_str("UnrelFun"),
     314             :                   unrel_fun->GetFunction(env.local()).ToLocalChecked())
     315             :             .FromJust());
     316          30 :   CHECK(env->Global()
     317             :             ->Set(env.local(), v8_str("fun_instance"), fun_instance)
     318             :             .FromJust());
     319          30 :   CHECK(env->Global()
     320             :             ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
     321             :             .FromJust());
     322          30 :   CHECK(env->Global()
     323             :             ->Set(env.local(), v8_str("direct_instance"), direct_instance)
     324             :             .FromJust());
     325             :   CompileRun(
     326             :       "var accessor_sig_key = 'accessor_sig';"
     327             :       "var accessor_key = 'accessor';"
     328             :       "var prop_sig_key = 'prop_sig';"
     329             :       "var prop_key = 'prop';"
     330             :       ""
     331             :       "function copy_props(obj) {"
     332             :       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
     333             :       "  var source = Fun.prototype;"
     334             :       "  for (var i in keys) {"
     335             :       "    var key = keys[i];"
     336             :       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
     337             :       "    Object.defineProperty(obj, key, desc);"
     338             :       "  }"
     339             :       "}"
     340             :       ""
     341             :       "var plain = {};"
     342             :       "copy_props(plain);"
     343             :       "var unrelated = new UnrelFun();"
     344             :       "copy_props(unrelated);"
     345             :       "var inherited = { __proto__: fun_instance };"
     346             :       "var inherited_direct = { __proto__: direct_instance };");
     347             :   // Test with and without ICs
     348             :   const char* test_objects[] = {
     349             :       "fun_instance", "sub_fun_instance", "direct_instance", "plain",
     350           6 :       "unrelated",    "inherited",        "inherited_direct"};
     351             :   unsigned bad_signature_start_offset = 3;
     352          48 :   for (unsigned i = 0; i < arraysize(test_objects); i++) {
     353             :     i::ScopedVector<char> source(200);
     354             :     i::SNPrintF(
     355          42 :         source, "var test_object = %s; test_object", test_objects[i]);
     356          42 :     Local<Value> test_object = CompileRun(source.start());
     357          42 :     TestSignature("test_object.prop();", test_object, isolate);
     358          42 :     TestSignature("test_object.accessor;", test_object, isolate);
     359          42 :     TestSignature("test_object[accessor_key];", test_object, isolate);
     360          42 :     TestSignature("test_object.accessor = 1;", test_object, isolate);
     361          42 :     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
     362          42 :     if (i >= bad_signature_start_offset) test_object = Local<Value>();
     363          42 :     TestSignature("test_object.prop_sig();", test_object, isolate);
     364          42 :     TestSignature("test_object.accessor_sig;", test_object, isolate);
     365          42 :     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
     366          42 :     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
     367          42 :     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
     368           6 :   }
     369           6 : }
     370             : 
     371             : 
     372       28343 : THREADED_TEST(HulIgennem) {
     373           6 :   LocalContext env;
     374           6 :   v8::Isolate* isolate = env->GetIsolate();
     375          12 :   v8::HandleScope scope(isolate);
     376             :   v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
     377           6 :   Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
     378           6 :   char* value = i::NewArray<char>(undef_str->Utf8Length(isolate) + 1);
     379           6 :   undef_str->WriteUtf8(isolate, value);
     380           6 :   CHECK_EQ(0, strcmp(value, "undefined"));
     381           6 :   i::DeleteArray(value);
     382           6 : }
     383             : 
     384             : 
     385       28343 : THREADED_TEST(Access) {
     386           6 :   LocalContext env;
     387           6 :   v8::Isolate* isolate = env->GetIsolate();
     388          12 :   v8::HandleScope scope(isolate);
     389           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
     390             :   Local<Value> foo_before =
     391          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     392           6 :   CHECK(foo_before->IsUndefined());
     393           6 :   Local<String> bar_str = v8_str("bar");
     394          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
     395             :   Local<Value> foo_after =
     396          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     397           6 :   CHECK(!foo_after->IsUndefined());
     398           6 :   CHECK(foo_after->IsString());
     399          12 :   CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
     400             : 
     401          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).ToChecked());
     402             :   bool result;
     403          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).To(&result));
     404          12 :   CHECK(result);
     405           6 : }
     406             : 
     407             : 
     408       28343 : THREADED_TEST(AccessElement) {
     409           6 :   LocalContext env;
     410          12 :   v8::HandleScope scope(env->GetIsolate());
     411           6 :   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
     412           6 :   Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
     413           6 :   CHECK(before->IsUndefined());
     414           6 :   Local<String> bar_str = v8_str("bar");
     415          12 :   CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
     416           6 :   Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
     417           6 :   CHECK(!after->IsUndefined());
     418           6 :   CHECK(after->IsString());
     419          12 :   CHECK(bar_str->Equals(env.local(), after).FromJust());
     420             : 
     421             :   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
     422          24 :   CHECK(v8_str("a")
     423             :             ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
     424             :             .FromJust());
     425          24 :   CHECK(v8_str("b")
     426             :             ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
     427           6 :             .FromJust());
     428           6 : }
     429             : 
     430             : 
     431       28343 : THREADED_TEST(Script) {
     432           6 :   LocalContext env;
     433          12 :   v8::HandleScope scope(env->GetIsolate());
     434             :   const char* source = "1 + 2 + 3";
     435           6 :   Local<Script> script = v8_compile(source);
     436          12 :   CHECK_EQ(6, v8_run_int32value(script));
     437           6 : }
     438             : 
     439             : 
     440             : class TestResource: public String::ExternalStringResource {
     441             :  public:
     442             :   explicit TestResource(uint16_t* data, int* counter = nullptr,
     443             :                         bool owning_data = true)
     444       17941 :       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
     445     3064640 :     while (data[length_]) ++length_;
     446             :   }
     447             : 
     448       35876 :   ~TestResource() override {
     449       17941 :     if (owning_data_) i::DeleteArray(data_);
     450       17941 :     if (counter_ != nullptr) ++*counter_;
     451       35876 :   }
     452             : 
     453       56579 :   const uint16_t* data() const override { return data_; }
     454             : 
     455       71698 :   size_t length() const override { return length_; }
     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          69 :         length_(strlen(data) - offset),
     472         148 :         counter_(counter) {}
     473             : 
     474         128 :   ~TestOneByteResource() override {
     475          69 :     i::DeleteArray(orig_data_);
     476          69 :     if (counter_ != nullptr) ++*counter_;
     477         128 :   }
     478             : 
     479         194 :   const char* data() const override { return data_; }
     480             : 
     481         183 :   size_t length() const override { return length_; }
     482             : 
     483             :  private:
     484             :   const char* orig_data_;
     485             :   const char* data_;
     486             :   size_t length_;
     487             :   int* counter_;
     488             : };
     489             : 
     490             : 
     491       28343 : THREADED_TEST(ScriptUsingStringResource) {
     492           6 :   int dispose_count = 0;
     493             :   const char* c_source = "1 + 2 * 3";
     494           6 :   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
     495             :   {
     496           6 :     LocalContext env;
     497          12 :     v8::HandleScope scope(env->GetIsolate());
     498           6 :     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
     499             :     Local<String> source =
     500           6 :         String::NewExternalTwoByte(env->GetIsolate(), resource)
     501           6 :             .ToLocalChecked();
     502           6 :     Local<Script> script = v8_compile(source);
     503          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     504           6 :     CHECK(value->IsNumber());
     505          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     506           6 :     CHECK(source->IsExternal());
     507           6 :     CHECK_EQ(resource,
     508             :              static_cast<TestResource*>(source->GetExternalStringResource()));
     509           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     510           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     511             :              source->GetExternalStringResourceBase(&encoding));
     512           6 :     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
     513           6 :     CcTest::CollectAllGarbage();
     514          12 :     CHECK_EQ(0, dispose_count);
     515             :   }
     516           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     517           6 :   CcTest::CollectAllAvailableGarbage();
     518           6 :   CHECK_EQ(1, dispose_count);
     519           6 : }
     520             : 
     521             : 
     522       28343 : THREADED_TEST(ScriptUsingOneByteStringResource) {
     523           6 :   int dispose_count = 0;
     524             :   const char* c_source = "1 + 2 * 3";
     525             :   {
     526           6 :     LocalContext env;
     527          12 :     v8::HandleScope scope(env->GetIsolate());
     528             :     TestOneByteResource* resource =
     529           6 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
     530             :     Local<String> source =
     531           6 :         String::NewExternalOneByte(env->GetIsolate(), resource)
     532           6 :             .ToLocalChecked();
     533           6 :     CHECK(source->IsExternalOneByte());
     534           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     535             :              source->GetExternalOneByteStringResource());
     536           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     537           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     538             :              source->GetExternalStringResourceBase(&encoding));
     539           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     540           6 :     Local<Script> script = v8_compile(source);
     541          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     542           6 :     CHECK(value->IsNumber());
     543          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     544           6 :     CcTest::CollectAllGarbage();
     545          12 :     CHECK_EQ(0, dispose_count);
     546             :   }
     547           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     548           6 :   CcTest::CollectAllAvailableGarbage();
     549           6 :   CHECK_EQ(1, dispose_count);
     550           6 : }
     551             : 
     552             : 
     553       28343 : THREADED_TEST(ScriptMakingExternalString) {
     554           6 :   int dispose_count = 0;
     555           6 :   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
     556             :   {
     557           6 :     LocalContext env;
     558          12 :     v8::HandleScope scope(env->GetIsolate());
     559             :     Local<String> source =
     560             :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     561           6 :                                v8::NewStringType::kNormal)
     562           6 :             .ToLocalChecked();
     563             :     // Trigger GCs so that the newly allocated string moves to old gen.
     564           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     565           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     566           6 :     CHECK(!source->IsExternal());
     567           6 :     CHECK(!source->IsExternalOneByte());
     568           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     569           6 :     CHECK(!source->GetExternalStringResourceBase(&encoding));
     570           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     571             :     bool success = source->MakeExternal(new TestResource(two_byte_source,
     572          12 :                                                          &dispose_count));
     573           6 :     CHECK(success);
     574           6 :     Local<Script> script = v8_compile(source);
     575          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     576           6 :     CHECK(value->IsNumber());
     577          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     578           6 :     CcTest::CollectAllGarbage();
     579          12 :     CHECK_EQ(0, dispose_count);
     580             :   }
     581           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     582           6 :   CcTest::CollectAllGarbage();
     583           6 :   CHECK_EQ(1, dispose_count);
     584           6 : }
     585             : 
     586             : 
     587       28343 : THREADED_TEST(ScriptMakingExternalOneByteString) {
     588           6 :   int dispose_count = 0;
     589             :   const char* c_source = "1 + 2 * 3";
     590             :   {
     591           6 :     LocalContext env;
     592          12 :     v8::HandleScope scope(env->GetIsolate());
     593           6 :     Local<String> source = v8_str(c_source);
     594             :     // Trigger GCs so that the newly allocated string moves to old gen.
     595           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     596           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     597             :     bool success = source->MakeExternal(
     598          12 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
     599           6 :     CHECK(success);
     600           6 :     Local<Script> script = v8_compile(source);
     601          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     602           6 :     CHECK(value->IsNumber());
     603          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     604           6 :     CcTest::CollectAllGarbage();
     605          12 :     CHECK_EQ(0, dispose_count);
     606             :   }
     607           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     608           6 :   CcTest::CollectAllGarbage();
     609           6 :   CHECK_EQ(1, dispose_count);
     610           6 : }
     611             : 
     612             : 
     613       28342 : TEST(MakingExternalStringConditions) {
     614           5 :   LocalContext env;
     615          10 :   v8::HandleScope scope(env->GetIsolate());
     616             : 
     617             :   // Free some space in the new space so that we can check freshness.
     618           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     619           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     620             : 
     621           5 :   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
     622             :   Local<String> local_string =
     623             :       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
     624           5 :                              v8::NewStringType::kNormal)
     625           5 :           .ToLocalChecked();
     626             :   i::DeleteArray(two_byte_string);
     627             : 
     628             :   // We should refuse to externalize new space strings.
     629           5 :   CHECK(!local_string->CanMakeExternal());
     630             :   // Trigger GCs so that the newly allocated string moves to old gen.
     631           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     632           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     633             :   // Old space strings should be accepted.
     634          10 :   CHECK(local_string->CanMakeExternal());
     635           5 : }
     636             : 
     637             : 
     638       28342 : TEST(MakingExternalOneByteStringConditions) {
     639           5 :   LocalContext env;
     640          10 :   v8::HandleScope scope(env->GetIsolate());
     641             : 
     642             :   // Free some space in the new space so that we can check freshness.
     643           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     644           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     645             : 
     646           5 :   Local<String> local_string = v8_str("s1");
     647             :   // We should refuse to externalize new space strings.
     648           5 :   CHECK(!local_string->CanMakeExternal());
     649             :   // Trigger GCs so that the newly allocated string moves to old gen.
     650           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     651           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     652             :   // Old space strings should be accepted.
     653          10 :   CHECK(local_string->CanMakeExternal());
     654           5 : }
     655             : 
     656             : 
     657       28342 : TEST(MakingExternalUnalignedOneByteString) {
     658           5 :   LocalContext env;
     659          10 :   v8::HandleScope scope(env->GetIsolate());
     660             : 
     661             :   CompileRun("function cons(a, b) { return a + b; }"
     662             :              "function slice(a) { return a.substring(1); }");
     663             :   // Create a cons string that will land in old pointer space.
     664             :   Local<String> cons = Local<String>::Cast(CompileRun(
     665             :       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
     666             :   // Create a sliced string that will land in old pointer space.
     667             :   Local<String> slice = Local<String>::Cast(CompileRun(
     668             :       "slice('abcdefghijklmnopqrstuvwxyz');"));
     669             : 
     670             :   // Trigger GCs so that the newly allocated string moves to old gen.
     671           5 :   i::heap::SimulateFullSpace(CcTest::heap()->old_space());
     672           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     673           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     674             : 
     675             :   // Turn into external string with unaligned resource data.
     676             :   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
     677             :   bool success = cons->MakeExternal(
     678          10 :       new TestOneByteResource(i::StrDup(c_cons), nullptr, 1));
     679           5 :   CHECK(success);
     680             :   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
     681             :   success = slice->MakeExternal(
     682          10 :       new TestOneByteResource(i::StrDup(c_slice), nullptr, 1));
     683           5 :   CHECK(success);
     684             : 
     685             :   // Trigger GCs and force evacuation.
     686           5 :   CcTest::CollectAllGarbage();
     687             :   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask,
     688          10 :                                     i::GarbageCollectionReason::kTesting);
     689           5 : }
     690             : 
     691       28343 : THREADED_TEST(UsingExternalString) {
     692             :   i::Factory* factory = CcTest::i_isolate()->factory();
     693             :   {
     694           6 :     v8::HandleScope scope(CcTest::isolate());
     695           6 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     696             :     Local<String> string =
     697             :         String::NewExternalTwoByte(CcTest::isolate(),
     698          12 :                                    new TestResource(two_byte_string))
     699           6 :             .ToLocalChecked();
     700           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     701             :     // Trigger GCs so that the newly allocated string moves to old gen.
     702           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     703           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     704             :     i::Handle<i::String> isymbol =
     705           6 :         factory->InternalizeString(istring);
     706          12 :     CHECK(isymbol->IsInternalizedString());
     707             :   }
     708           6 :   CcTest::CollectAllGarbage();
     709           6 :   CcTest::CollectAllGarbage();
     710           6 : }
     711             : 
     712             : 
     713       28343 : THREADED_TEST(UsingExternalOneByteString) {
     714             :   i::Factory* factory = CcTest::i_isolate()->factory();
     715             :   {
     716           6 :     v8::HandleScope scope(CcTest::isolate());
     717             :     const char* one_byte_string = "test string";
     718             :     Local<String> string =
     719             :         String::NewExternalOneByte(
     720             :             CcTest::isolate(),
     721          12 :             new TestOneByteResource(i::StrDup(one_byte_string)))
     722           6 :             .ToLocalChecked();
     723           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     724             :     // Trigger GCs so that the newly allocated string moves to old gen.
     725           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     726           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     727             :     i::Handle<i::String> isymbol =
     728           6 :         factory->InternalizeString(istring);
     729          12 :     CHECK(isymbol->IsInternalizedString());
     730             :   }
     731           6 :   CcTest::CollectAllGarbage();
     732           6 :   CcTest::CollectAllGarbage();
     733           6 : }
     734             : 
     735             : 
     736           6 : class RandomLengthResource : public v8::String::ExternalStringResource {
     737             :  public:
     738           6 :   explicit RandomLengthResource(int length) : length_(length) {}
     739           6 :   const uint16_t* data() const override { return string_; }
     740           6 :   size_t length() const override { return length_; }
     741             : 
     742             :  private:
     743             :   uint16_t string_[10];
     744             :   int length_;
     745             : };
     746             : 
     747             : 
     748          16 : class RandomLengthOneByteResource
     749             :     : public v8::String::ExternalOneByteStringResource {
     750             :  public:
     751          11 :   explicit RandomLengthOneByteResource(int length) : length_(length) {}
     752          16 :   const char* data() const override { return string_; }
     753          26 :   size_t length() const override { return length_; }
     754             : 
     755             :  private:
     756             :   char string_[10];
     757             :   int length_;
     758             : };
     759             : 
     760             : 
     761       28343 : THREADED_TEST(NewExternalForVeryLongString) {
     762           6 :   auto isolate = CcTest::isolate();
     763             :   {
     764           6 :     v8::HandleScope scope(isolate);
     765          12 :     v8::TryCatch try_catch(isolate);
     766             :     RandomLengthOneByteResource r(1 << 30);
     767             :     v8::MaybeLocal<v8::String> maybe_str =
     768           6 :         v8::String::NewExternalOneByte(isolate, &r);
     769           6 :     CHECK(maybe_str.IsEmpty());
     770          12 :     CHECK(!try_catch.HasCaught());
     771             :   }
     772             : 
     773             :   {
     774           6 :     v8::HandleScope scope(isolate);
     775          12 :     v8::TryCatch try_catch(isolate);
     776             :     RandomLengthResource r(1 << 30);
     777             :     v8::MaybeLocal<v8::String> maybe_str =
     778           6 :         v8::String::NewExternalTwoByte(isolate, &r);
     779           6 :     CHECK(maybe_str.IsEmpty());
     780          12 :     CHECK(!try_catch.HasCaught());
     781             :   }
     782           6 : }
     783             : 
     784       28342 : TEST(ScavengeExternalString) {
     785             :   ManualGCScope manual_gc_scope;
     786           5 :   i::FLAG_stress_compaction = false;
     787           5 :   i::FLAG_gc_global = false;
     788           5 :   int dispose_count = 0;
     789             :   bool in_new_space = false;
     790             :   {
     791           5 :     v8::HandleScope scope(CcTest::isolate());
     792           5 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     793             :     Local<String> string =
     794             :         String::NewExternalTwoByte(
     795             :             CcTest::isolate(),
     796          10 :             new TestResource(two_byte_string, &dispose_count))
     797           5 :             .ToLocalChecked();
     798             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     799           5 :     CcTest::CollectGarbage(i::NEW_SPACE);
     800             :     in_new_space = i::Heap::InNewSpace(*istring);
     801          10 :     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
     802           5 :     CHECK_EQ(0, dispose_count);
     803             :   }
     804           5 :   CcTest::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
     805           5 :   CHECK_EQ(1, dispose_count);
     806           5 : }
     807             : 
     808       28342 : TEST(ScavengeExternalOneByteString) {
     809             :   ManualGCScope manual_gc_scope;
     810           5 :   i::FLAG_stress_compaction = false;
     811           5 :   i::FLAG_gc_global = false;
     812           5 :   int dispose_count = 0;
     813             :   bool in_new_space = false;
     814             :   {
     815           5 :     v8::HandleScope scope(CcTest::isolate());
     816             :     const char* one_byte_string = "test string";
     817             :     Local<String> string =
     818             :         String::NewExternalOneByte(
     819             :             CcTest::isolate(),
     820          10 :             new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
     821           5 :             .ToLocalChecked();
     822             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     823           5 :     CcTest::CollectGarbage(i::NEW_SPACE);
     824             :     in_new_space = i::Heap::InNewSpace(*istring);
     825          10 :     CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
     826           5 :     CHECK_EQ(0, dispose_count);
     827             :   }
     828           5 :   CcTest::CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
     829           5 :   CHECK_EQ(1, dispose_count);
     830           5 : }
     831             : 
     832             : 
     833          10 : class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
     834             :  public:
     835             :   // Only used by non-threaded tests, so it can use static fields.
     836             :   static int dispose_calls;
     837             :   static int dispose_count;
     838             : 
     839             :   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
     840          10 :       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
     841             : 
     842          10 :   void Dispose() override {
     843          10 :     ++dispose_calls;
     844          10 :     if (dispose_) delete this;
     845          10 :   }
     846             :  private:
     847             :   bool dispose_;
     848             : };
     849             : 
     850             : 
     851             : int TestOneByteResourceWithDisposeControl::dispose_count = 0;
     852             : int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     853             : 
     854             : 
     855       28342 : TEST(ExternalStringWithDisposeHandling) {
     856             :   const char* c_source = "1 + 2 * 3";
     857             : 
     858             :   // Use a stack allocated external string resource allocated object.
     859           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     860           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     861           5 :   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
     862             :   {
     863           5 :     LocalContext env;
     864          10 :     v8::HandleScope scope(env->GetIsolate());
     865             :     Local<String> source =
     866           5 :         String::NewExternalOneByte(env->GetIsolate(), &res_stack)
     867          10 :             .ToLocalChecked();
     868           5 :     Local<Script> script = v8_compile(source);
     869          10 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     870           5 :     CHECK(value->IsNumber());
     871          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     872           5 :     CcTest::CollectAllAvailableGarbage();
     873          10 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     874             :   }
     875           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     876           5 :   CcTest::CollectAllAvailableGarbage();
     877           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     878           5 :   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     879             : 
     880             :   // Use a heap allocated external string resource allocated object.
     881           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     882           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     883             :   TestOneByteResource* res_heap =
     884           5 :       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
     885             :   {
     886           5 :     LocalContext env;
     887          10 :     v8::HandleScope scope(env->GetIsolate());
     888             :     Local<String> source =
     889           5 :         String::NewExternalOneByte(env->GetIsolate(), res_heap)
     890          10 :             .ToLocalChecked();
     891           5 :     Local<Script> script = v8_compile(source);
     892          10 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     893           5 :     CHECK(value->IsNumber());
     894          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     895           5 :     CcTest::CollectAllAvailableGarbage();
     896          10 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     897             :   }
     898           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     899           5 :   CcTest::CollectAllAvailableGarbage();
     900           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     901           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
     902           5 : }
     903             : 
     904             : 
     905       28343 : THREADED_TEST(StringConcat) {
     906             :   {
     907           6 :     LocalContext env;
     908           6 :     v8::Isolate* isolate = env->GetIsolate();
     909          12 :     v8::HandleScope scope(isolate);
     910             :     const char* one_byte_string_1 = "function a_times_t";
     911             :     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
     912             :     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
     913             :     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
     914             :     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     915             :     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     916             :     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
     917           6 :     Local<String> left = v8_str(one_byte_string_1);
     918             : 
     919           6 :     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
     920             :     Local<String> right =
     921             :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     922           6 :                                v8::NewStringType::kNormal)
     923          12 :             .ToLocalChecked();
     924             :     i::DeleteArray(two_byte_source);
     925             : 
     926           6 :     Local<String> source = String::Concat(isolate, left, right);
     927             :     right = String::NewExternalOneByte(
     928             :                 env->GetIsolate(),
     929          12 :                 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
     930          12 :                 .ToLocalChecked();
     931           6 :     source = String::Concat(isolate, source, right);
     932             :     right = String::NewExternalTwoByte(
     933             :                 env->GetIsolate(),
     934          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
     935          12 :                 .ToLocalChecked();
     936           6 :     source = String::Concat(isolate, source, right);
     937           6 :     right = v8_str(one_byte_string_2);
     938           6 :     source = String::Concat(isolate, source, right);
     939             : 
     940           6 :     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
     941             :     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     942           6 :                                    v8::NewStringType::kNormal)
     943          12 :                 .ToLocalChecked();
     944             :     i::DeleteArray(two_byte_source);
     945             : 
     946           6 :     source = String::Concat(isolate, source, right);
     947             :     right = String::NewExternalTwoByte(
     948             :                 env->GetIsolate(),
     949          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
     950          12 :                 .ToLocalChecked();
     951           6 :     source = String::Concat(isolate, source, right);
     952           6 :     Local<Script> script = v8_compile(source);
     953          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     954           6 :     CHECK(value->IsNumber());
     955          18 :     CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
     956             :   }
     957           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     958           6 :   CcTest::CollectAllGarbage();
     959           6 :   CcTest::CollectAllGarbage();
     960           6 : }
     961             : 
     962             : 
     963       28343 : THREADED_TEST(GlobalProperties) {
     964           6 :   LocalContext env;
     965          12 :   v8::HandleScope scope(env->GetIsolate());
     966           6 :   v8::Local<v8::Object> global = env->Global();
     967          18 :   CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
     968          18 :   Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
     969          18 :   CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
     970           6 : }
     971             : 
     972             : 
     973        1980 : static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
     974             :                                  i::Address callback) {
     975         660 :   ApiTestFuzzer::Fuzz();
     976         660 :   CheckReturnValue(info, callback);
     977         660 :   info.GetReturnValue().Set(v8_str("bad value"));
     978         660 :   info.GetReturnValue().Set(v8_num(102));
     979         660 : }
     980             : 
     981             : 
     982         330 : static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
     983         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
     984             : }
     985             : 
     986             : 
     987         330 : static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
     988         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
     989             : }
     990             : 
     991          22 : static void construct_callback(
     992         154 :     const v8::FunctionCallbackInfo<Value>& info) {
     993          22 :   ApiTestFuzzer::Fuzz();
     994          22 :   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
     995          88 :   CHECK(
     996             :       info.This()
     997             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
     998             :           .FromJust());
     999          88 :   CHECK(
    1000             :       info.This()
    1001             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
    1002             :           .FromJust());
    1003          22 :   info.GetReturnValue().Set(v8_str("bad value"));
    1004             :   info.GetReturnValue().Set(info.This());
    1005          22 : }
    1006             : 
    1007             : 
    1008         330 : static void Return239Callback(
    1009             :     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    1010         330 :   ApiTestFuzzer::Fuzz();
    1011         330 :   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    1012         330 :   info.GetReturnValue().Set(v8_str("bad value"));
    1013         330 :   info.GetReturnValue().Set(v8_num(239));
    1014         330 : }
    1015             : 
    1016             : 
    1017             : template<typename Handler>
    1018          11 : static void TestFunctionTemplateInitializer(Handler handler,
    1019             :                                             Handler handler_2) {
    1020             :   // Test constructor calls.
    1021             :   {
    1022          11 :     LocalContext env;
    1023          11 :     v8::Isolate* isolate = env->GetIsolate();
    1024          22 :     v8::HandleScope scope(isolate);
    1025             : 
    1026             :     Local<v8::FunctionTemplate> fun_templ =
    1027          11 :         v8::FunctionTemplate::New(isolate, handler);
    1028          22 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1029          55 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1030          11 :     Local<Script> script = v8_compile("obj()");
    1031         341 :     for (int i = 0; i < 30; i++) {
    1032         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1033          11 :     }
    1034             :   }
    1035             :   // Use SetCallHandler to initialize a function template, should work like
    1036             :   // the previous one.
    1037             :   {
    1038          11 :     LocalContext env;
    1039          11 :     v8::Isolate* isolate = env->GetIsolate();
    1040          22 :     v8::HandleScope scope(isolate);
    1041             : 
    1042          11 :     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
    1043          11 :     fun_templ->SetCallHandler(handler_2);
    1044          11 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1045          55 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1046          11 :     Local<Script> script = v8_compile("obj()");
    1047         341 :     for (int i = 0; i < 30; i++) {
    1048         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1049          11 :     }
    1050             :   }
    1051          11 : }
    1052             : 
    1053             : 
    1054             : template<typename Constructor, typename Accessor>
    1055          11 : static void TestFunctionTemplateAccessor(Constructor constructor,
    1056             :                                          Accessor accessor) {
    1057          11 :   LocalContext env;
    1058          22 :   v8::HandleScope scope(env->GetIsolate());
    1059             : 
    1060             :   Local<v8::FunctionTemplate> fun_templ =
    1061          11 :       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
    1062          11 :   fun_templ->SetClassName(v8_str("funky"));
    1063          22 :   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
    1064          11 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1065          55 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1066             :   Local<Value> result =
    1067          33 :       v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
    1068          33 :   CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
    1069             :   CompileRun("var obj_instance = new obj();");
    1070             :   Local<Script> script;
    1071          11 :   script = v8_compile("obj_instance.x");
    1072         341 :   for (int i = 0; i < 30; i++) {
    1073         330 :     CHECK_EQ(1, v8_run_int32value(script));
    1074             :   }
    1075          11 :   script = v8_compile("obj_instance.m");
    1076         341 :   for (int i = 0; i < 30; i++) {
    1077         330 :     CHECK_EQ(239, v8_run_int32value(script));
    1078          11 :   }
    1079          11 : }
    1080             : 
    1081             : 
    1082       56690 : THREADED_PROFILED_TEST(FunctionTemplate) {
    1083          11 :   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
    1084          11 :   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
    1085          11 : }
    1086             : 
    1087          18 : static void FunctionCallbackForProxyTest(
    1088          36 :     const v8::FunctionCallbackInfo<Value>& info) {
    1089             :   info.GetReturnValue().Set(info.This());
    1090          18 : }
    1091             : 
    1092       28343 : THREADED_TEST(FunctionTemplateWithProxy) {
    1093           6 :   LocalContext env;
    1094           6 :   v8::Isolate* isolate = env->GetIsolate();
    1095          12 :   v8::HandleScope scope(isolate);
    1096             : 
    1097             :   v8::Local<v8::FunctionTemplate> function_template =
    1098           6 :       v8::FunctionTemplate::New(isolate, FunctionCallbackForProxyTest);
    1099             :   v8::Local<v8::Function> function =
    1100          12 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1101          30 :   CHECK((*env)->Global()->Set(env.local(), v8_str("f"), function).FromJust());
    1102             :   v8::Local<v8::Value> proxy =
    1103             :       CompileRun("var proxy = new Proxy({}, {}); proxy");
    1104           6 :   CHECK(proxy->IsProxy());
    1105             : 
    1106             :   v8::Local<v8::Value> result = CompileRun("f(proxy)");
    1107          18 :   CHECK(result->Equals(env.local(), (*env)->Global()).FromJust());
    1108             : 
    1109             :   result = CompileRun("f.call(proxy)");
    1110          12 :   CHECK(result->Equals(env.local(), proxy).FromJust());
    1111             : 
    1112             :   result = CompileRun("Reflect.apply(f, proxy, [1])");
    1113          18 :   CHECK(result->Equals(env.local(), proxy).FromJust());
    1114           6 : }
    1115             : 
    1116        1980 : static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    1117         660 :   ApiTestFuzzer::Fuzz();
    1118         660 :   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
    1119         660 :   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
    1120         660 : }
    1121             : 
    1122             : 
    1123             : template<typename Callback>
    1124          11 : static void TestSimpleCallback(Callback callback) {
    1125          11 :   LocalContext env;
    1126          11 :   v8::Isolate* isolate = env->GetIsolate();
    1127          22 :   v8::HandleScope scope(isolate);
    1128             : 
    1129             :   v8::Local<v8::ObjectTemplate> object_template =
    1130          11 :       v8::ObjectTemplate::New(isolate);
    1131          22 :   object_template->Set(isolate, "callback",
    1132             :                        v8::FunctionTemplate::New(isolate, callback));
    1133             :   v8::Local<v8::Object> object =
    1134          11 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1135          55 :   CHECK((*env)
    1136             :             ->Global()
    1137             :             ->Set(env.local(), v8_str("callback_object"), object)
    1138             :             .FromJust());
    1139             :   v8::Local<v8::Script> script;
    1140          11 :   script = v8_compile("callback_object.callback(17)");
    1141         341 :   for (int i = 0; i < 30; i++) {
    1142         330 :     CHECK_EQ(51424, v8_run_int32value(script));
    1143             :   }
    1144          11 :   script = v8_compile("callback_object.callback(17, 24)");
    1145         341 :   for (int i = 0; i < 30; i++) {
    1146         330 :     CHECK_EQ(51425, v8_run_int32value(script));
    1147          11 :   }
    1148          11 : }
    1149             : 
    1150             : 
    1151       56690 : THREADED_PROFILED_TEST(SimpleCallback) {
    1152          11 :   TestSimpleCallback(SimpleCallback);
    1153          11 : }
    1154             : 
    1155             : 
    1156             : template<typename T>
    1157             : void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
    1158             : 
    1159             : // constant return values
    1160             : static int32_t fast_return_value_int32 = 471;
    1161             : static uint32_t fast_return_value_uint32 = 571;
    1162             : static const double kFastReturnValueDouble = 2.7;
    1163             : // variable return values
    1164             : static bool fast_return_value_bool = false;
    1165             : enum ReturnValueOddball {
    1166             :   kNullReturnValue,
    1167             :   kUndefinedReturnValue,
    1168             :   kEmptyStringReturnValue
    1169             : };
    1170             : static ReturnValueOddball fast_return_value_void;
    1171             : static bool fast_return_value_object_is_empty = false;
    1172             : 
    1173             : // Helper function to avoid compiler error: insufficient contextual information
    1174             : // to determine type when applying FUNCTION_ADDR to a template function.
    1175             : static i::Address address_of(v8::FunctionCallback callback) {
    1176         396 :   return FUNCTION_ADDR(callback);
    1177             : }
    1178             : 
    1179             : template<>
    1180         165 : void FastReturnValueCallback<int32_t>(
    1181         165 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1182         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
    1183         165 :   info.GetReturnValue().Set(fast_return_value_int32);
    1184         165 : }
    1185             : 
    1186             : template<>
    1187         165 : void FastReturnValueCallback<uint32_t>(
    1188         165 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1189         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
    1190         165 :   info.GetReturnValue().Set(fast_return_value_uint32);
    1191         165 : }
    1192             : 
    1193             : template<>
    1194          11 : void FastReturnValueCallback<double>(
    1195          11 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1196          11 :   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
    1197             :   info.GetReturnValue().Set(kFastReturnValueDouble);
    1198          11 : }
    1199             : 
    1200             : template<>
    1201          22 : void FastReturnValueCallback<bool>(
    1202          22 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1203          22 :   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
    1204          22 :   info.GetReturnValue().Set(fast_return_value_bool);
    1205          22 : }
    1206             : 
    1207             : template<>
    1208          33 : void FastReturnValueCallback<void>(
    1209          33 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1210          33 :   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
    1211          33 :   switch (fast_return_value_void) {
    1212             :     case kNullReturnValue:
    1213             :       info.GetReturnValue().SetNull();
    1214          11 :       break;
    1215             :     case kUndefinedReturnValue:
    1216             :       info.GetReturnValue().SetUndefined();
    1217          11 :       break;
    1218             :     case kEmptyStringReturnValue:
    1219             :       info.GetReturnValue().SetEmptyString();
    1220          11 :       break;
    1221             :   }
    1222          33 : }
    1223             : 
    1224             : template<>
    1225          22 : void FastReturnValueCallback<Object>(
    1226          33 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1227             :   v8::Local<v8::Object> object;
    1228          22 :   if (!fast_return_value_object_is_empty) {
    1229          11 :     object = Object::New(info.GetIsolate());
    1230             :   }
    1231             :   info.GetReturnValue().Set(object);
    1232          22 : }
    1233             : 
    1234             : template <typename T>
    1235         418 : Local<Value> TestFastReturnValues() {
    1236         418 :   LocalContext env;
    1237         418 :   v8::Isolate* isolate = env->GetIsolate();
    1238         418 :   v8::EscapableHandleScope scope(isolate);
    1239             :   v8::Local<v8::ObjectTemplate> object_template =
    1240         418 :       v8::ObjectTemplate::New(isolate);
    1241             :   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
    1242             :   object_template->Set(isolate, "callback",
    1243         836 :                        v8::FunctionTemplate::New(isolate, callback));
    1244             :   v8::Local<v8::Object> object =
    1245         418 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1246        2090 :   CHECK((*env)
    1247             :             ->Global()
    1248             :             ->Set(env.local(), v8_str("callback_object"), object)
    1249             :             .FromJust());
    1250         418 :   return scope.Escape(CompileRun("callback_object.callback()"));
    1251             : }
    1252             : 
    1253             : 
    1254       56690 : THREADED_PROFILED_TEST(FastReturnValues) {
    1255          11 :   LocalContext env;
    1256          11 :   v8::Isolate* isolate = env->GetIsolate();
    1257          22 :   v8::HandleScope scope(isolate);
    1258             :   v8::Local<v8::Value> value;
    1259             :   // check int32_t and uint32_t
    1260             :   int32_t int_values[] = {
    1261             :       0, 234, -723,
    1262             :       i::Smi::kMinValue, i::Smi::kMaxValue
    1263          11 :   };
    1264          66 :   for (size_t i = 0; i < arraysize(int_values); i++) {
    1265         165 :     for (int modifier = -1; modifier <= 1; modifier++) {
    1266         165 :       int int_value = v8::base::AddWithWraparound(int_values[i], modifier);
    1267             :       // check int32_t
    1268         165 :       fast_return_value_int32 = int_value;
    1269         165 :       value = TestFastReturnValues<int32_t>();
    1270         165 :       CHECK(value->IsInt32());
    1271         330 :       CHECK_EQ(fast_return_value_int32,
    1272             :                value->Int32Value(env.local()).FromJust());
    1273             :       // check uint32_t
    1274         165 :       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
    1275         165 :       value = TestFastReturnValues<uint32_t>();
    1276         165 :       CHECK(value->IsUint32());
    1277         330 :       CHECK_EQ(fast_return_value_uint32,
    1278             :                value->Uint32Value(env.local()).FromJust());
    1279             :     }
    1280             :   }
    1281             :   // check double
    1282          11 :   value = TestFastReturnValues<double>();
    1283          11 :   CHECK(value->IsNumber());
    1284          22 :   CHECK_EQ(kFastReturnValueDouble,
    1285             :            value->ToNumber(env.local()).ToLocalChecked()->Value());
    1286             :   // check bool values
    1287          22 :   for (int i = 0; i < 2; i++) {
    1288          22 :     fast_return_value_bool = i == 0;
    1289          22 :     value = TestFastReturnValues<bool>();
    1290          22 :     CHECK(value->IsBoolean());
    1291          22 :     CHECK_EQ(fast_return_value_bool, value->BooleanValue(isolate));
    1292             :   }
    1293             :   // check oddballs
    1294             :   ReturnValueOddball oddballs[] = {
    1295             :       kNullReturnValue,
    1296             :       kUndefinedReturnValue,
    1297             :       kEmptyStringReturnValue
    1298          11 :   };
    1299          44 :   for (size_t i = 0; i < arraysize(oddballs); i++) {
    1300          33 :     fast_return_value_void = oddballs[i];
    1301          33 :     value = TestFastReturnValues<void>();
    1302          33 :     switch (fast_return_value_void) {
    1303             :       case kNullReturnValue:
    1304          11 :         CHECK(value->IsNull());
    1305             :         break;
    1306             :       case kUndefinedReturnValue:
    1307          11 :         CHECK(value->IsUndefined());
    1308             :         break;
    1309             :       case kEmptyStringReturnValue:
    1310          11 :         CHECK(value->IsString());
    1311          11 :         CHECK_EQ(0, v8::String::Cast(*value)->Length());
    1312             :         break;
    1313             :     }
    1314             :   }
    1315             :   // check handles
    1316          11 :   fast_return_value_object_is_empty = false;
    1317          11 :   value = TestFastReturnValues<Object>();
    1318          11 :   CHECK(value->IsObject());
    1319          11 :   fast_return_value_object_is_empty = true;
    1320          11 :   value = TestFastReturnValues<Object>();
    1321          22 :   CHECK(value->IsUndefined());
    1322          11 : }
    1323             : 
    1324             : 
    1325       28343 : THREADED_TEST(FunctionTemplateSetLength) {
    1326           6 :   LocalContext env;
    1327           6 :   v8::Isolate* isolate = env->GetIsolate();
    1328          12 :   v8::HandleScope scope(isolate);
    1329             :   {
    1330             :     Local<v8::FunctionTemplate> fun_templ =
    1331             :         v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
    1332           6 :                                   Local<v8::Signature>(), 23);
    1333          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1334          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1335           6 :     Local<Script> script = v8_compile("obj.length");
    1336           6 :     CHECK_EQ(23, v8_run_int32value(script));
    1337             :   }
    1338             :   {
    1339             :     Local<v8::FunctionTemplate> fun_templ =
    1340           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1341           6 :     fun_templ->SetLength(22);
    1342           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1343          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1344           6 :     Local<Script> script = v8_compile("obj.length");
    1345           6 :     CHECK_EQ(22, v8_run_int32value(script));
    1346             :   }
    1347             :   {
    1348             :     // Without setting length it defaults to 0.
    1349             :     Local<v8::FunctionTemplate> fun_templ =
    1350           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1351          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1352          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1353           6 :     Local<Script> script = v8_compile("obj.length");
    1354           6 :     CHECK_EQ(0, v8_run_int32value(script));
    1355           6 :   }
    1356           6 : }
    1357             : 
    1358             : 
    1359             : static void* expected_ptr;
    1360       16848 : static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1361        8424 :   void* ptr = v8::External::Cast(*args.Data())->Value();
    1362        8424 :   CHECK_EQ(expected_ptr, ptr);
    1363             :   args.GetReturnValue().Set(true);
    1364        8424 : }
    1365             : 
    1366             : 
    1367         648 : static void TestExternalPointerWrapping() {
    1368         648 :   LocalContext env;
    1369         648 :   v8::Isolate* isolate = env->GetIsolate();
    1370        1296 :   v8::HandleScope scope(isolate);
    1371             : 
    1372         648 :   v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
    1373             : 
    1374         648 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    1375        4536 :   CHECK(obj->Set(env.local(), v8_str("func"),
    1376             :                  v8::FunctionTemplate::New(isolate, callback, data)
    1377             :                      ->GetFunction(env.local())
    1378             :                      .ToLocalChecked())
    1379             :             .FromJust());
    1380        3240 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
    1381             : 
    1382         648 :   CHECK(CompileRun("function foo() {\n"
    1383             :                    "  for (var i = 0; i < 13; i++) obj.func();\n"
    1384             :                    "}\n"
    1385             :                    "foo(), true")
    1386         648 :             ->BooleanValue(isolate));
    1387         648 : }
    1388             : 
    1389             : 
    1390       28343 : THREADED_TEST(ExternalWrap) {
    1391             :   // Check heap allocated object.
    1392           6 :   int* ptr = new int;
    1393           6 :   expected_ptr = ptr;
    1394           6 :   TestExternalPointerWrapping();
    1395           6 :   delete ptr;
    1396             : 
    1397             :   // Check stack allocated object.
    1398             :   int foo;
    1399           6 :   expected_ptr = &foo;
    1400           6 :   TestExternalPointerWrapping();
    1401             : 
    1402             :   // Check not aligned addresses.
    1403             :   const int n = 100;
    1404           6 :   char* s = new char[n];
    1405         606 :   for (int i = 0; i < n; i++) {
    1406         600 :     expected_ptr = s + i;
    1407         600 :     TestExternalPointerWrapping();
    1408             :   }
    1409             : 
    1410           6 :   delete[] s;
    1411             : 
    1412             :   // Check several invalid addresses.
    1413           6 :   expected_ptr = reinterpret_cast<void*>(1);
    1414           6 :   TestExternalPointerWrapping();
    1415             : 
    1416           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEF);
    1417           6 :   TestExternalPointerWrapping();
    1418             : 
    1419           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEF + 1);
    1420           6 :   TestExternalPointerWrapping();
    1421             : 
    1422             : #if defined(V8_HOST_ARCH_X64)
    1423             :   // Check a value with a leading 1 bit in x64 Smi encoding.
    1424           6 :   expected_ptr = reinterpret_cast<void*>(0x400000000);
    1425           6 :   TestExternalPointerWrapping();
    1426             : 
    1427           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEFDEADBEEF);
    1428           6 :   TestExternalPointerWrapping();
    1429             : 
    1430           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEFDEADBEEF + 1);
    1431           6 :   TestExternalPointerWrapping();
    1432             : #endif
    1433           6 : }
    1434             : 
    1435             : 
    1436       28343 : THREADED_TEST(FindInstanceInPrototypeChain) {
    1437           6 :   LocalContext env;
    1438           6 :   v8::Isolate* isolate = env->GetIsolate();
    1439          12 :   v8::HandleScope scope(isolate);
    1440             : 
    1441           6 :   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
    1442           6 :   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
    1443           6 :   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
    1444           6 :   derived->Inherit(base);
    1445             : 
    1446             :   Local<v8::Function> base_function =
    1447          12 :       base->GetFunction(env.local()).ToLocalChecked();
    1448             :   Local<v8::Function> derived_function =
    1449           6 :       derived->GetFunction(env.local()).ToLocalChecked();
    1450             :   Local<v8::Function> other_function =
    1451          12 :       other->GetFunction(env.local()).ToLocalChecked();
    1452             : 
    1453             :   Local<v8::Object> base_instance =
    1454           6 :       base_function->NewInstance(env.local()).ToLocalChecked();
    1455             :   Local<v8::Object> derived_instance =
    1456           6 :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1457             :   Local<v8::Object> derived_instance2 =
    1458           6 :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1459             :   Local<v8::Object> other_instance =
    1460           6 :       other_function->NewInstance(env.local()).ToLocalChecked();
    1461          18 :   CHECK(
    1462             :       derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
    1463             :           .FromJust());
    1464          18 :   CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
    1465             :             .FromJust());
    1466             : 
    1467             :   // base_instance is only an instance of base.
    1468          18 :   CHECK(base_instance->Equals(env.local(),
    1469             :                               base_instance->FindInstanceInPrototypeChain(base))
    1470             :             .FromJust());
    1471          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
    1472          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1473             : 
    1474             :   // derived_instance is an instance of base and derived.
    1475          18 :   CHECK(derived_instance->Equals(env.local(),
    1476             :                                  derived_instance->FindInstanceInPrototypeChain(
    1477             :                                      base))
    1478             :             .FromJust());
    1479          18 :   CHECK(derived_instance->Equals(env.local(),
    1480             :                                  derived_instance->FindInstanceInPrototypeChain(
    1481             :                                      derived))
    1482             :             .FromJust());
    1483          12 :   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1484             : 
    1485             :   // other_instance is an instance of other and its immediate
    1486             :   // prototype derived_instance2 is an instance of base and derived.
    1487             :   // Note, derived_instance is an instance of base and derived too,
    1488             :   // but it comes after derived_instance2 in the prototype chain of
    1489             :   // other_instance.
    1490          18 :   CHECK(derived_instance2->Equals(
    1491             :                              env.local(),
    1492             :                              other_instance->FindInstanceInPrototypeChain(base))
    1493             :             .FromJust());
    1494          18 :   CHECK(derived_instance2->Equals(env.local(),
    1495             :                                   other_instance->FindInstanceInPrototypeChain(
    1496             :                                       derived))
    1497             :             .FromJust());
    1498          18 :   CHECK(other_instance->Equals(
    1499             :                           env.local(),
    1500             :                           other_instance->FindInstanceInPrototypeChain(other))
    1501           6 :             .FromJust());
    1502           6 : }
    1503             : 
    1504             : 
    1505       28343 : THREADED_TEST(TinyInteger) {
    1506           6 :   LocalContext env;
    1507           6 :   v8::Isolate* isolate = env->GetIsolate();
    1508          12 :   v8::HandleScope scope(isolate);
    1509             : 
    1510             :   int32_t value = 239;
    1511           6 :   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1512          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1513           6 : }
    1514             : 
    1515             : 
    1516       28343 : THREADED_TEST(BigSmiInteger) {
    1517           6 :   LocalContext env;
    1518          12 :   v8::HandleScope scope(env->GetIsolate());
    1519           6 :   v8::Isolate* isolate = CcTest::isolate();
    1520             : 
    1521             :   int32_t value = i::Smi::kMaxValue;
    1522             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1523             :   if (i::SmiValuesAre31Bits()) {
    1524             :     CHECK(i::Smi::IsValid(value));
    1525             :     CHECK(!i::Smi::IsValid(value + 1));
    1526             : 
    1527             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1528             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1529           6 :   }
    1530           6 : }
    1531             : 
    1532             : 
    1533       28343 : THREADED_TEST(BigInteger) {
    1534           6 :   LocalContext env;
    1535          12 :   v8::HandleScope scope(env->GetIsolate());
    1536           6 :   v8::Isolate* isolate = CcTest::isolate();
    1537             : 
    1538             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1539             :   if (i::SmiValuesAre31Bits()) {
    1540             :     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
    1541             :     // The code will not be run in that case, due to the "if" guard.
    1542             :     int32_t value =
    1543             :         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
    1544             :     CHECK_GT(value, i::Smi::kMaxValue);
    1545             :     CHECK(!i::Smi::IsValid(value));
    1546             : 
    1547             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1548             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1549           6 :   }
    1550           6 : }
    1551             : 
    1552             : 
    1553       28343 : THREADED_TEST(TinyUnsignedInteger) {
    1554           6 :   LocalContext env;
    1555          12 :   v8::HandleScope scope(env->GetIsolate());
    1556           6 :   v8::Isolate* isolate = CcTest::isolate();
    1557             : 
    1558             :   uint32_t value = 239;
    1559             : 
    1560           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1561          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1562           6 : }
    1563             : 
    1564             : 
    1565       28343 : THREADED_TEST(BigUnsignedSmiInteger) {
    1566           6 :   LocalContext env;
    1567          12 :   v8::HandleScope scope(env->GetIsolate());
    1568           6 :   v8::Isolate* isolate = CcTest::isolate();
    1569             : 
    1570             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
    1571             :   CHECK(i::Smi::IsValid(value));
    1572             :   CHECK(!i::Smi::IsValid(value + 1));
    1573             : 
    1574           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1575          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1576           6 : }
    1577             : 
    1578             : 
    1579       28343 : THREADED_TEST(BigUnsignedInteger) {
    1580           6 :   LocalContext env;
    1581          12 :   v8::HandleScope scope(env->GetIsolate());
    1582           6 :   v8::Isolate* isolate = CcTest::isolate();
    1583             : 
    1584             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
    1585             :   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
    1586             :   CHECK(!i::Smi::IsValid(value));
    1587             : 
    1588           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1589          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1590           6 : }
    1591             : 
    1592             : 
    1593       28343 : THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
    1594           6 :   LocalContext env;
    1595          12 :   v8::HandleScope scope(env->GetIsolate());
    1596           6 :   v8::Isolate* isolate = CcTest::isolate();
    1597             : 
    1598             :   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
    1599             :   uint32_t value = INT32_MAX_AS_UINT + 1;
    1600             :   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
    1601             : 
    1602           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1603          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1604           6 : }
    1605             : 
    1606             : 
    1607       28343 : THREADED_TEST(IsNativeError) {
    1608           6 :   LocalContext env;
    1609          12 :   v8::HandleScope scope(env->GetIsolate());
    1610             :   v8::Local<Value> syntax_error = CompileRun(
    1611             :       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
    1612           6 :   CHECK(syntax_error->IsNativeError());
    1613             :   v8::Local<Value> not_error = CompileRun("{a:42}");
    1614           6 :   CHECK(!not_error->IsNativeError());
    1615             :   v8::Local<Value> not_object = CompileRun("42");
    1616          12 :   CHECK(!not_object->IsNativeError());
    1617           6 : }
    1618             : 
    1619             : 
    1620       28343 : THREADED_TEST(IsGeneratorFunctionOrObject) {
    1621           6 :   LocalContext env;
    1622          12 :   v8::HandleScope scope(env->GetIsolate());
    1623             : 
    1624             :   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
    1625             :   v8::Local<Value> gen = CompileRun("gen");
    1626             :   v8::Local<Value> genObj = CompileRun("gen()");
    1627             :   v8::Local<Value> object = CompileRun("{a:42}");
    1628             :   v8::Local<Value> func = CompileRun("func");
    1629             : 
    1630           6 :   CHECK(gen->IsGeneratorFunction());
    1631           6 :   CHECK(gen->IsFunction());
    1632           6 :   CHECK(!gen->IsGeneratorObject());
    1633             : 
    1634           6 :   CHECK(!genObj->IsGeneratorFunction());
    1635           6 :   CHECK(!genObj->IsFunction());
    1636           6 :   CHECK(genObj->IsGeneratorObject());
    1637             : 
    1638           6 :   CHECK(!object->IsGeneratorFunction());
    1639           6 :   CHECK(!object->IsFunction());
    1640           6 :   CHECK(!object->IsGeneratorObject());
    1641             : 
    1642           6 :   CHECK(!func->IsGeneratorFunction());
    1643           6 :   CHECK(func->IsFunction());
    1644          12 :   CHECK(!func->IsGeneratorObject());
    1645           6 : }
    1646             : 
    1647       28343 : THREADED_TEST(IsAsyncFunction) {
    1648           6 :   LocalContext env;
    1649           6 :   v8::Isolate* isolate = env->GetIsolate();
    1650          12 :   v8::HandleScope scope(isolate);
    1651             : 
    1652             :   CompileRun("async function foo() {}");
    1653             :   v8::Local<Value> foo = CompileRun("foo");
    1654             : 
    1655           6 :   CHECK(foo->IsAsyncFunction());
    1656           6 :   CHECK(foo->IsFunction());
    1657           6 :   CHECK(!foo->IsGeneratorFunction());
    1658           6 :   CHECK(!foo->IsGeneratorObject());
    1659             : 
    1660             :   CompileRun("function bar() {}");
    1661             :   v8::Local<Value> bar = CompileRun("bar");
    1662             : 
    1663           6 :   CHECK(!bar->IsAsyncFunction());
    1664          12 :   CHECK(bar->IsFunction());
    1665           6 : }
    1666             : 
    1667       28343 : THREADED_TEST(ArgumentsObject) {
    1668           6 :   LocalContext env;
    1669          12 :   v8::HandleScope scope(env->GetIsolate());
    1670             :   v8::Local<Value> arguments_object =
    1671             :       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
    1672           6 :   CHECK(arguments_object->IsArgumentsObject());
    1673             :   v8::Local<Value> array = CompileRun("[1,2,3]");
    1674           6 :   CHECK(!array->IsArgumentsObject());
    1675             :   v8::Local<Value> object = CompileRun("{a:42}");
    1676          12 :   CHECK(!object->IsArgumentsObject());
    1677           6 : }
    1678             : 
    1679             : 
    1680       28343 : THREADED_TEST(IsMapOrSet) {
    1681           6 :   LocalContext env;
    1682          12 :   v8::HandleScope scope(env->GetIsolate());
    1683             :   v8::Local<Value> map = CompileRun("new Map()");
    1684             :   v8::Local<Value> set = CompileRun("new Set()");
    1685             :   v8::Local<Value> weak_map = CompileRun("new WeakMap()");
    1686             :   v8::Local<Value> weak_set = CompileRun("new WeakSet()");
    1687           6 :   CHECK(map->IsMap());
    1688           6 :   CHECK(set->IsSet());
    1689           6 :   CHECK(weak_map->IsWeakMap());
    1690           6 :   CHECK(weak_set->IsWeakSet());
    1691             : 
    1692           6 :   CHECK(!map->IsSet());
    1693           6 :   CHECK(!map->IsWeakMap());
    1694           6 :   CHECK(!map->IsWeakSet());
    1695             : 
    1696           6 :   CHECK(!set->IsMap());
    1697           6 :   CHECK(!set->IsWeakMap());
    1698           6 :   CHECK(!set->IsWeakSet());
    1699             : 
    1700           6 :   CHECK(!weak_map->IsMap());
    1701           6 :   CHECK(!weak_map->IsSet());
    1702           6 :   CHECK(!weak_map->IsWeakSet());
    1703             : 
    1704           6 :   CHECK(!weak_set->IsMap());
    1705           6 :   CHECK(!weak_set->IsSet());
    1706           6 :   CHECK(!weak_set->IsWeakMap());
    1707             : 
    1708             :   v8::Local<Value> object = CompileRun("{a:42}");
    1709           6 :   CHECK(!object->IsMap());
    1710           6 :   CHECK(!object->IsSet());
    1711           6 :   CHECK(!object->IsWeakMap());
    1712          12 :   CHECK(!object->IsWeakSet());
    1713           6 : }
    1714             : 
    1715             : 
    1716       28343 : THREADED_TEST(StringObject) {
    1717           6 :   LocalContext env;
    1718          12 :   v8::HandleScope scope(env->GetIsolate());
    1719             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1720           6 :   CHECK(boxed_string->IsStringObject());
    1721             :   v8::Local<Value> unboxed_string = CompileRun("\"test\"");
    1722           6 :   CHECK(!unboxed_string->IsStringObject());
    1723             :   v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
    1724           6 :   CHECK(!boxed_not_string->IsStringObject());
    1725             :   v8::Local<Value> not_object = CompileRun("0");
    1726           6 :   CHECK(!not_object->IsStringObject());
    1727             :   v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
    1728           6 :   CHECK(!as_boxed.IsEmpty());
    1729           6 :   Local<v8::String> the_string = as_boxed->ValueOf();
    1730           6 :   CHECK(!the_string.IsEmpty());
    1731           6 :   ExpectObject("\"test\"", the_string);
    1732             :   v8::Local<v8::Value> new_boxed_string =
    1733           6 :       v8::StringObject::New(CcTest::isolate(), the_string);
    1734           6 :   CHECK(new_boxed_string->IsStringObject());
    1735             :   as_boxed = new_boxed_string.As<v8::StringObject>();
    1736           6 :   the_string = as_boxed->ValueOf();
    1737           6 :   CHECK(!the_string.IsEmpty());
    1738          12 :   ExpectObject("\"test\"", the_string);
    1739           6 : }
    1740             : 
    1741             : 
    1742       28342 : TEST(StringObjectDelete) {
    1743           5 :   LocalContext context;
    1744          10 :   v8::HandleScope scope(context->GetIsolate());
    1745             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1746           5 :   CHECK(boxed_string->IsStringObject());
    1747             :   v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
    1748          10 :   CHECK(!str_obj->Delete(context.local(), 2).FromJust());
    1749          15 :   CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
    1750           5 : }
    1751             : 
    1752             : 
    1753       28343 : THREADED_TEST(NumberObject) {
    1754           6 :   LocalContext env;
    1755          12 :   v8::HandleScope scope(env->GetIsolate());
    1756             :   v8::Local<Value> boxed_number = CompileRun("new Number(42)");
    1757           6 :   CHECK(boxed_number->IsNumberObject());
    1758             :   v8::Local<Value> unboxed_number = CompileRun("42");
    1759           6 :   CHECK(!unboxed_number->IsNumberObject());
    1760             :   v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
    1761           6 :   CHECK(!boxed_not_number->IsNumberObject());
    1762             :   v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
    1763           6 :   CHECK(!as_boxed.IsEmpty());
    1764           6 :   double the_number = as_boxed->ValueOf();
    1765           6 :   CHECK_EQ(42.0, the_number);
    1766             :   v8::Local<v8::Value> new_boxed_number =
    1767           6 :       v8::NumberObject::New(env->GetIsolate(), 43);
    1768           6 :   CHECK(new_boxed_number->IsNumberObject());
    1769             :   as_boxed = new_boxed_number.As<v8::NumberObject>();
    1770           6 :   the_number = as_boxed->ValueOf();
    1771          12 :   CHECK_EQ(43.0, the_number);
    1772           6 : }
    1773             : 
    1774       28343 : THREADED_TEST(BigIntObject) {
    1775           6 :   LocalContext env;
    1776           6 :   v8::Isolate* isolate = env->GetIsolate();
    1777          12 :   v8::HandleScope scope(isolate);
    1778           6 :   v8::Local<v8::Context> context(env.local());
    1779             :   v8::Local<Value> boxed_bigint = CompileRun("new Object(42n)");
    1780           6 :   CHECK(!boxed_bigint->IsBigInt());
    1781           6 :   CHECK(boxed_bigint->IsBigIntObject());
    1782             :   v8::Local<Value> unboxed_bigint = CompileRun("42n");
    1783           6 :   CHECK(unboxed_bigint->IsBigInt());
    1784           6 :   CHECK(!unboxed_bigint->IsBigIntObject());
    1785             :   v8::Local<v8::BigIntObject> as_boxed = boxed_bigint.As<v8::BigIntObject>();
    1786           6 :   CHECK(!as_boxed.IsEmpty());
    1787           6 :   v8::Local<v8::BigInt> unpacked = as_boxed->ValueOf();
    1788           6 :   CHECK(!unpacked.IsEmpty());
    1789           6 :   v8::Local<v8::Value> new_boxed_bigint = v8::BigIntObject::New(isolate, 43);
    1790           6 :   CHECK(new_boxed_bigint->IsBigIntObject());
    1791           6 :   v8::Local<v8::Value> new_unboxed_bigint = v8::BigInt::New(isolate, 44);
    1792           6 :   CHECK(new_unboxed_bigint->IsBigInt());
    1793             : 
    1794             :   // Test functionality inherited from v8::Value.
    1795           6 :   CHECK(unboxed_bigint->BooleanValue(isolate));
    1796             :   v8::Local<v8::String> string =
    1797           6 :       unboxed_bigint->ToString(context).ToLocalChecked();
    1798           6 :   CHECK_EQ(0, strcmp("42", *v8::String::Utf8Value(isolate, string)));
    1799             : 
    1800             :   // IntegerValue throws.
    1801          18 :   CHECK(unboxed_bigint->IntegerValue(context).IsNothing());
    1802           6 : }
    1803             : 
    1804       28343 : THREADED_TEST(BooleanObject) {
    1805           6 :   LocalContext env;
    1806          12 :   v8::HandleScope scope(env->GetIsolate());
    1807             :   v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
    1808           6 :   CHECK(boxed_boolean->IsBooleanObject());
    1809             :   v8::Local<Value> unboxed_boolean = CompileRun("true");
    1810           6 :   CHECK(!unboxed_boolean->IsBooleanObject());
    1811             :   v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
    1812           6 :   CHECK(!boxed_not_boolean->IsBooleanObject());
    1813             :   v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
    1814           6 :   CHECK(!as_boxed.IsEmpty());
    1815           6 :   bool the_boolean = as_boxed->ValueOf();
    1816           6 :   CHECK(the_boolean);
    1817             :   v8::Local<v8::Value> boxed_true =
    1818           6 :       v8::BooleanObject::New(env->GetIsolate(), true);
    1819             :   v8::Local<v8::Value> boxed_false =
    1820           6 :       v8::BooleanObject::New(env->GetIsolate(), false);
    1821           6 :   CHECK(boxed_true->IsBooleanObject());
    1822           6 :   CHECK(boxed_false->IsBooleanObject());
    1823             :   as_boxed = boxed_true.As<v8::BooleanObject>();
    1824           6 :   CHECK(as_boxed->ValueOf());
    1825             :   as_boxed = boxed_false.As<v8::BooleanObject>();
    1826          12 :   CHECK(!as_boxed->ValueOf());
    1827           6 : }
    1828             : 
    1829             : 
    1830       28343 : THREADED_TEST(PrimitiveAndWrappedBooleans) {
    1831           6 :   LocalContext env;
    1832           6 :   v8::Isolate* isolate = env->GetIsolate();
    1833          12 :   v8::HandleScope scope(isolate);
    1834             : 
    1835             :   Local<Value> primitive_false = Boolean::New(isolate, false);
    1836           6 :   CHECK(primitive_false->IsBoolean());
    1837           6 :   CHECK(!primitive_false->IsBooleanObject());
    1838           6 :   CHECK(!primitive_false->BooleanValue(isolate));
    1839           6 :   CHECK(!primitive_false->IsTrue());
    1840           6 :   CHECK(primitive_false->IsFalse());
    1841             : 
    1842           6 :   Local<Value> false_value = BooleanObject::New(isolate, false);
    1843           6 :   CHECK(!false_value->IsBoolean());
    1844           6 :   CHECK(false_value->IsBooleanObject());
    1845           6 :   CHECK(false_value->BooleanValue(isolate));
    1846           6 :   CHECK(!false_value->IsTrue());
    1847           6 :   CHECK(!false_value->IsFalse());
    1848             : 
    1849             :   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
    1850           6 :   CHECK(!false_boolean_object->IsBoolean());
    1851           6 :   CHECK(false_boolean_object->IsBooleanObject());
    1852           6 :   CHECK(false_boolean_object->BooleanValue(isolate));
    1853           6 :   CHECK(!false_boolean_object->ValueOf());
    1854           6 :   CHECK(!false_boolean_object->IsTrue());
    1855           6 :   CHECK(!false_boolean_object->IsFalse());
    1856             : 
    1857             :   Local<Value> primitive_true = Boolean::New(isolate, true);
    1858           6 :   CHECK(primitive_true->IsBoolean());
    1859           6 :   CHECK(!primitive_true->IsBooleanObject());
    1860           6 :   CHECK(primitive_true->BooleanValue(isolate));
    1861           6 :   CHECK(primitive_true->IsTrue());
    1862           6 :   CHECK(!primitive_true->IsFalse());
    1863             : 
    1864           6 :   Local<Value> true_value = BooleanObject::New(isolate, true);
    1865           6 :   CHECK(!true_value->IsBoolean());
    1866           6 :   CHECK(true_value->IsBooleanObject());
    1867           6 :   CHECK(true_value->BooleanValue(isolate));
    1868           6 :   CHECK(!true_value->IsTrue());
    1869           6 :   CHECK(!true_value->IsFalse());
    1870             : 
    1871             :   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
    1872           6 :   CHECK(!true_boolean_object->IsBoolean());
    1873           6 :   CHECK(true_boolean_object->IsBooleanObject());
    1874           6 :   CHECK(true_boolean_object->BooleanValue(isolate));
    1875           6 :   CHECK(true_boolean_object->ValueOf());
    1876           6 :   CHECK(!true_boolean_object->IsTrue());
    1877          12 :   CHECK(!true_boolean_object->IsFalse());
    1878           6 : }
    1879             : 
    1880             : 
    1881       28343 : THREADED_TEST(Number) {
    1882           6 :   LocalContext env;
    1883          12 :   v8::HandleScope scope(env->GetIsolate());
    1884             :   double PI = 3.1415926;
    1885           6 :   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
    1886          24 :   CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
    1887           6 : }
    1888             : 
    1889             : 
    1890       28343 : THREADED_TEST(ToNumber) {
    1891           6 :   LocalContext env;
    1892           6 :   v8::Isolate* isolate = CcTest::isolate();
    1893          12 :   v8::HandleScope scope(isolate);
    1894           6 :   Local<String> str = v8_str("3.1415926");
    1895          18 :   CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
    1896             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1897          12 :   CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
    1898             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1899          18 :   CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
    1900           6 : }
    1901             : 
    1902             : 
    1903       28343 : THREADED_TEST(Date) {
    1904           6 :   LocalContext env;
    1905          12 :   v8::HandleScope scope(env->GetIsolate());
    1906             :   double PI = 3.1415926;
    1907           6 :   Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
    1908          12 :   CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
    1909          24 :   CHECK(date.As<v8::Date>()
    1910             :             ->Set(env.local(), v8_str("property"),
    1911             :                   v8::Integer::New(env->GetIsolate(), 42))
    1912             :             .FromJust());
    1913          24 :   CHECK_EQ(42, date.As<v8::Date>()
    1914             :                    ->Get(env.local(), v8_str("property"))
    1915             :                    .ToLocalChecked()
    1916             :                    ->Int32Value(env.local())
    1917           6 :                    .FromJust());
    1918           6 : }
    1919             : 
    1920             : 
    1921       28343 : THREADED_TEST(Boolean) {
    1922           6 :   LocalContext env;
    1923           6 :   v8::Isolate* isolate = env->GetIsolate();
    1924          12 :   v8::HandleScope scope(isolate);
    1925             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1926           6 :   CHECK(t->Value());
    1927             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1928           6 :   CHECK(!f->Value());
    1929             :   v8::Local<v8::Primitive> u = v8::Undefined(isolate);
    1930           6 :   CHECK(!u->BooleanValue(isolate));
    1931             :   v8::Local<v8::Primitive> n = v8::Null(isolate);
    1932           6 :   CHECK(!n->BooleanValue(isolate));
    1933           6 :   v8::Local<String> str1 = v8_str("");
    1934           6 :   CHECK(!str1->BooleanValue(isolate));
    1935           6 :   v8::Local<String> str2 = v8_str("x");
    1936           6 :   CHECK(str2->BooleanValue(isolate));
    1937          12 :   CHECK(!v8::Number::New(isolate, 0)->BooleanValue(isolate));
    1938          12 :   CHECK(v8::Number::New(isolate, -1)->BooleanValue(isolate));
    1939          12 :   CHECK(v8::Number::New(isolate, 1)->BooleanValue(isolate));
    1940          12 :   CHECK(v8::Number::New(isolate, 42)->BooleanValue(isolate));
    1941          18 :   CHECK(!v8_compile("NaN")
    1942             :              ->Run(env.local())
    1943             :              .ToLocalChecked()
    1944           6 :              ->BooleanValue(isolate));
    1945           6 : }
    1946             : 
    1947             : 
    1948          12 : static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1949           6 :   ApiTestFuzzer::Fuzz();
    1950           6 :   args.GetReturnValue().Set(v8_num(13.4));
    1951           6 : }
    1952             : 
    1953             : 
    1954           6 : static void GetM(Local<String> name,
    1955             :                  const v8::PropertyCallbackInfo<v8::Value>& info) {
    1956           6 :   ApiTestFuzzer::Fuzz();
    1957           6 :   info.GetReturnValue().Set(v8_num(876));
    1958           6 : }
    1959             : 
    1960             : 
    1961       28343 : THREADED_TEST(GlobalPrototype) {
    1962           6 :   v8::Isolate* isolate = CcTest::isolate();
    1963           6 :   v8::HandleScope scope(isolate);
    1964             :   v8::Local<v8::FunctionTemplate> func_templ =
    1965           6 :       v8::FunctionTemplate::New(isolate);
    1966          12 :   func_templ->PrototypeTemplate()->Set(
    1967          12 :       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
    1968           6 :   v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
    1969           6 :   templ->Set(isolate, "x", v8_num(200));
    1970           6 :   templ->SetAccessor(v8_str("m"), GetM);
    1971          12 :   LocalContext env(nullptr, templ);
    1972             :   v8::Local<Script> script(v8_compile("dummy()"));
    1973           6 :   v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
    1974          12 :   CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
    1975           6 :   CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
    1976          12 :   CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
    1977           6 : }
    1978             : 
    1979             : 
    1980       28343 : THREADED_TEST(ObjectTemplate) {
    1981           6 :   LocalContext env;
    1982           6 :   v8::Isolate* isolate = CcTest::isolate();
    1983          12 :   v8::HandleScope scope(isolate);
    1984             :   Local<v8::FunctionTemplate> acc =
    1985           6 :       v8::FunctionTemplate::New(isolate, Returns42);
    1986          42 :   CHECK(env->Global()
    1987             :             ->Set(env.local(), v8_str("acc"),
    1988             :                   acc->GetFunction(env.local()).ToLocalChecked())
    1989             :             .FromJust());
    1990             : 
    1991           6 :   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    1992           6 :   v8::Local<v8::String> class_name = v8_str("the_class_name");
    1993           6 :   fun->SetClassName(class_name);
    1994           6 :   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
    1995           6 :   templ1->Set(isolate, "x", v8_num(10));
    1996           6 :   templ1->Set(isolate, "y", v8_num(13));
    1997          12 :   templ1->Set(v8_str("foo"), acc);
    1998             :   Local<v8::Object> instance1 =
    1999           6 :       templ1->NewInstance(env.local()).ToLocalChecked();
    2000          12 :   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
    2001          30 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
    2002           6 :   CHECK(CompileRun("(p.x == 10)")->BooleanValue(isolate));
    2003           6 :   CHECK(CompileRun("(p.y == 13)")->BooleanValue(isolate));
    2004           6 :   CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(isolate));
    2005           6 :   CHECK(CompileRun("(p.foo == acc)")->BooleanValue(isolate));
    2006             :   // Ensure that foo become a data field.
    2007             :   CompileRun("p.foo = function() {}");
    2008           6 :   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
    2009          12 :   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
    2010           6 :   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
    2011           6 :   templ2->Set(isolate, "a", v8_num(12));
    2012             :   templ2->Set(isolate, "b", templ1);
    2013          12 :   templ2->Set(v8_str("bar"), acc);
    2014          12 :   templ2->SetAccessorProperty(v8_str("acc"), acc);
    2015             :   Local<v8::Object> instance2 =
    2016           6 :       templ2->NewInstance(env.local()).ToLocalChecked();
    2017          30 :   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
    2018           6 :   CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(isolate));
    2019           6 :   CHECK(CompileRun("(q.a == 12)")->BooleanValue(isolate));
    2020           6 :   CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(isolate));
    2021           6 :   CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(isolate));
    2022           6 :   CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(isolate));
    2023           6 :   CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(isolate));
    2024           6 :   CHECK(CompileRun("(q.b !== p)")->BooleanValue(isolate));
    2025           6 :   CHECK(CompileRun("(q.acc == 42)")->BooleanValue(isolate));
    2026           6 :   CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(isolate));
    2027           6 :   CHECK(CompileRun("(q.bar == acc)")->BooleanValue(isolate));
    2028             : 
    2029           6 :   instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
    2030          30 :   CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
    2031           6 :   CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(isolate));
    2032           6 :   CHECK(CompileRun("(q2.a == 12)")->BooleanValue(isolate));
    2033           6 :   CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(isolate));
    2034           6 :   CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(isolate));
    2035           6 :   CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(isolate));
    2036           6 :   CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(isolate));
    2037           6 :   CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(isolate));
    2038           6 :   CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(isolate));
    2039           6 :   CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(isolate));
    2040             : 
    2041           6 :   CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(isolate));
    2042           6 :   CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")->BooleanValue(isolate));
    2043           6 :   CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
    2044             :                    "(desc1.get === acc)")
    2045             :             ->BooleanValue(isolate));
    2046           6 :   CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
    2047             :                    "(desc2.get === acc)")
    2048           6 :             ->BooleanValue(isolate));
    2049           6 : }
    2050             : 
    2051       28343 : THREADED_TEST(IntegerValue) {
    2052           6 :   LocalContext env;
    2053           6 :   v8::Isolate* isolate = CcTest::isolate();
    2054          12 :   v8::HandleScope scope(isolate);
    2055             : 
    2056          24 :   CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
    2057           6 : }
    2058             : 
    2059         126 : static void GetNirk(Local<String> name,
    2060             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2061         126 :   ApiTestFuzzer::Fuzz();
    2062         126 :   info.GetReturnValue().Set(v8_num(900));
    2063         126 : }
    2064             : 
    2065         126 : static void GetRino(Local<String> name,
    2066             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2067         126 :   ApiTestFuzzer::Fuzz();
    2068         126 :   info.GetReturnValue().Set(v8_num(560));
    2069         126 : }
    2070             : 
    2071             : enum ObjectInstantiationMode {
    2072             :   // Create object using ObjectTemplate::NewInstance.
    2073             :   ObjectTemplate_NewInstance,
    2074             :   // Create object using FunctionTemplate::NewInstance on constructor.
    2075             :   Constructor_GetFunction_NewInstance,
    2076             :   // Create object using new operator on constructor.
    2077             :   Constructor_GetFunction_New
    2078             : };
    2079             : 
    2080             : // Test object instance creation using a function template with an instance
    2081             : // template inherited from another function template with accessors and data
    2082             : // properties in prototype template.
    2083          18 : static void TestObjectTemplateInheritedWithPrototype(
    2084             :     ObjectInstantiationMode mode) {
    2085          18 :   LocalContext env;
    2086          18 :   v8::Isolate* isolate = CcTest::isolate();
    2087          36 :   v8::HandleScope scope(isolate);
    2088             : 
    2089          18 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2090          18 :   fun_A->SetClassName(v8_str("A"));
    2091          18 :   v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
    2092          18 :   prototype_templ->Set(isolate, "a", v8_num(113));
    2093          18 :   prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2094          18 :   prototype_templ->Set(isolate, "b", v8_num(153));
    2095             : 
    2096          18 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2097          18 :   v8::Local<v8::String> class_name = v8_str("B");
    2098          18 :   fun_B->SetClassName(class_name);
    2099          18 :   fun_B->Inherit(fun_A);
    2100          18 :   prototype_templ = fun_B->PrototypeTemplate();
    2101          18 :   prototype_templ->Set(isolate, "c", v8_num(713));
    2102          18 :   prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
    2103          18 :   prototype_templ->Set(isolate, "d", v8_num(753));
    2104             : 
    2105          18 :   Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
    2106          18 :   templ->Set(isolate, "x", v8_num(10));
    2107          18 :   templ->Set(isolate, "y", v8_num(13));
    2108             : 
    2109             :   // Perform several iterations to trigger creation from cached boilerplate.
    2110          72 :   for (int i = 0; i < 3; i++) {
    2111             :     Local<v8::Object> instance;
    2112          54 :     switch (mode) {
    2113             :       case ObjectTemplate_NewInstance:
    2114          18 :         instance = templ->NewInstance(env.local()).ToLocalChecked();
    2115          18 :         break;
    2116             : 
    2117             :       case Constructor_GetFunction_NewInstance: {
    2118             :         Local<v8::Function> function_B =
    2119          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2120          18 :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2121             :         break;
    2122             :       }
    2123             :       case Constructor_GetFunction_New: {
    2124             :         Local<v8::Function> function_B =
    2125          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2126          18 :         if (i == 0) {
    2127          24 :           CHECK(env->Global()
    2128             :                     ->Set(env.local(), class_name, function_B)
    2129             :                     .FromJust());
    2130             :         }
    2131             :         instance =
    2132          36 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2133             :         break;
    2134             :       }
    2135             :       default:
    2136           0 :         UNREACHABLE();
    2137             :     }
    2138             : 
    2139         108 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2140         270 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2141             : 
    2142         162 :     CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
    2143         162 :     CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
    2144             : 
    2145         162 :     CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
    2146         162 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2147         162 :     CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
    2148         162 :     CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
    2149         162 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2150         162 :     CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
    2151          18 :   }
    2152          18 : }
    2153             : 
    2154       28343 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
    2155           6 :   TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
    2156           6 : }
    2157             : 
    2158       28343 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
    2159           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
    2160           6 : }
    2161             : 
    2162       28343 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
    2163           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
    2164           6 : }
    2165             : 
    2166             : // Test object instance creation using a function template without an instance
    2167             : // template inherited from another function template.
    2168          12 : static void TestObjectTemplateInheritedWithoutInstanceTemplate(
    2169             :     ObjectInstantiationMode mode) {
    2170          12 :   LocalContext env;
    2171          12 :   v8::Isolate* isolate = CcTest::isolate();
    2172          24 :   v8::HandleScope scope(isolate);
    2173             : 
    2174          12 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2175          12 :   fun_A->SetClassName(v8_str("A"));
    2176             : 
    2177          12 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2178          12 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2179          12 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2180             : 
    2181          12 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2182          12 :   v8::Local<v8::String> class_name = v8_str("B");
    2183          12 :   fun_B->SetClassName(class_name);
    2184          12 :   fun_B->Inherit(fun_A);
    2185             : 
    2186             :   // Perform several iterations to trigger creation from cached boilerplate.
    2187          48 :   for (int i = 0; i < 3; i++) {
    2188             :     Local<v8::Object> instance;
    2189          36 :     switch (mode) {
    2190             :       case Constructor_GetFunction_NewInstance: {
    2191             :         Local<v8::Function> function_B =
    2192          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2193          18 :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2194             :         break;
    2195             :       }
    2196             :       case Constructor_GetFunction_New: {
    2197             :         Local<v8::Function> function_B =
    2198          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2199          18 :         if (i == 0) {
    2200          24 :           CHECK(env->Global()
    2201             :                     ->Set(env.local(), class_name, function_B)
    2202             :                     .FromJust());
    2203             :         }
    2204             :         instance =
    2205          36 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2206             :         break;
    2207             :       }
    2208             :       default:
    2209           0 :         UNREACHABLE();
    2210             :     }
    2211             : 
    2212          72 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2213         180 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2214             : 
    2215         108 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2216         108 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2217          12 :   }
    2218          12 : }
    2219             : 
    2220       28343 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
    2221             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2222           6 :       Constructor_GetFunction_NewInstance);
    2223           6 : }
    2224             : 
    2225       28343 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
    2226             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2227           6 :       Constructor_GetFunction_New);
    2228           6 : }
    2229             : 
    2230       28343 : THREADED_TEST(TestObjectTemplateClassInheritance) {
    2231           6 :   LocalContext env;
    2232           6 :   v8::Isolate* isolate = CcTest::isolate();
    2233          12 :   v8::HandleScope scope(isolate);
    2234             : 
    2235           6 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2236           6 :   fun_A->SetClassName(v8_str("A"));
    2237             : 
    2238           6 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2239           6 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2240           6 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2241             : 
    2242           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2243           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2244           6 :   fun_B->SetClassName(class_name);
    2245           6 :   fun_B->Inherit(fun_A);
    2246             : 
    2247           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2248             :   v8::Local<v8::Object> b_proto;
    2249             :   v8::Local<v8::Object> c_proto;
    2250             :   // Perform several iterations to make sure the cache doesn't break
    2251             :   // subclassing.
    2252          24 :   for (int i = 0; i < 3; i++) {
    2253             :     Local<v8::Function> function_B =
    2254          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2255          18 :     if (i == 0) {
    2256          24 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2257             :       CompileRun("class C extends B {}");
    2258             :       b_proto =
    2259          12 :           CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
    2260             :       c_proto =
    2261          12 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2262          12 :       CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
    2263             :     }
    2264             :     Local<v8::Object> instance =
    2265          36 :         CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
    2266          36 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2267             : 
    2268          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2269          90 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2270             : 
    2271          54 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2272          54 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2273           6 :   }
    2274           6 : }
    2275             : 
    2276         276 : static void NamedPropertyGetterWhichReturns42(
    2277             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2278         276 :   info.GetReturnValue().Set(v8_num(42));
    2279         276 : }
    2280             : 
    2281       28343 : THREADED_TEST(TestObjectTemplateReflectConstruct) {
    2282           6 :   LocalContext env;
    2283           6 :   v8::Isolate* isolate = CcTest::isolate();
    2284          12 :   v8::HandleScope scope(isolate);
    2285             : 
    2286           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2287             :   fun_B->InstanceTemplate()->SetHandler(
    2288          12 :       v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
    2289           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2290           6 :   fun_B->SetClassName(class_name);
    2291             : 
    2292           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2293             :   v8::Local<v8::Object> b_proto;
    2294             :   v8::Local<v8::Object> c_proto;
    2295             :   // Perform several iterations to make sure the cache doesn't break
    2296             :   // subclassing.
    2297          24 :   for (int i = 0; i < 3; i++) {
    2298             :     Local<v8::Function> function_B =
    2299          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2300          18 :     if (i == 0) {
    2301          24 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2302             :       CompileRun("function C() {}");
    2303             :       c_proto =
    2304          12 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2305             :     }
    2306             :     Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
    2307          18 :                                      ->ToObject(env.local())
    2308          18 :                                      .ToLocalChecked();
    2309          36 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2310             : 
    2311          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2312          90 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2313             : 
    2314          54 :     CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2315          54 :     CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2316           6 :   }
    2317           6 : }
    2318             : 
    2319          24 : static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
    2320          12 :   ApiTestFuzzer::Fuzz();
    2321          12 :   args.GetReturnValue().Set(v8_num(17.2));
    2322          12 : }
    2323             : 
    2324             : 
    2325          30 : static void GetKnurd(Local<String> property,
    2326             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    2327          30 :   ApiTestFuzzer::Fuzz();
    2328          30 :   info.GetReturnValue().Set(v8_num(15.2));
    2329          30 : }
    2330             : 
    2331             : 
    2332       28343 : THREADED_TEST(DescriptorInheritance) {
    2333           6 :   v8::Isolate* isolate = CcTest::isolate();
    2334           6 :   v8::HandleScope scope(isolate);
    2335           6 :   v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
    2336          12 :   super->PrototypeTemplate()->Set(isolate, "flabby",
    2337             :                                   v8::FunctionTemplate::New(isolate,
    2338          12 :                                                             GetFlabby));
    2339          12 :   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
    2340             : 
    2341          12 :   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
    2342             : 
    2343           6 :   v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
    2344           6 :   base1->Inherit(super);
    2345          12 :   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
    2346             : 
    2347           6 :   v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
    2348           6 :   base2->Inherit(super);
    2349          12 :   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
    2350             : 
    2351          12 :   LocalContext env;
    2352             : 
    2353          36 :   CHECK(env->Global()
    2354             :             ->Set(env.local(), v8_str("s"),
    2355             :                   super->GetFunction(env.local()).ToLocalChecked())
    2356             :             .FromJust());
    2357          36 :   CHECK(env->Global()
    2358             :             ->Set(env.local(), v8_str("base1"),
    2359             :                   base1->GetFunction(env.local()).ToLocalChecked())
    2360             :             .FromJust());
    2361          36 :   CHECK(env->Global()
    2362             :             ->Set(env.local(), v8_str("base2"),
    2363             :                   base2->GetFunction(env.local()).ToLocalChecked())
    2364             :             .FromJust());
    2365             : 
    2366             :   // Checks right __proto__ chain.
    2367           6 :   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
    2368             :             ->BooleanValue(isolate));
    2369           6 :   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
    2370             :             ->BooleanValue(isolate));
    2371             : 
    2372          18 :   CHECK(v8_compile("s.prototype.PI == 3.14")
    2373             :             ->Run(env.local())
    2374             :             .ToLocalChecked()
    2375             :             ->BooleanValue(isolate));
    2376             : 
    2377             :   // Instance accessor should not be visible on function object or its prototype
    2378           6 :   CHECK(CompileRun("s.knurd == undefined")->BooleanValue(isolate));
    2379           6 :   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue(isolate));
    2380           6 :   CHECK(
    2381             :       CompileRun("base1.prototype.knurd == undefined")->BooleanValue(isolate));
    2382             : 
    2383          36 :   CHECK(env->Global()
    2384             :             ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
    2385             :                                                   .ToLocalChecked()
    2386             :                                                   ->NewInstance(env.local())
    2387             :                                                   .ToLocalChecked())
    2388             :             .FromJust());
    2389          18 :   CHECK_EQ(17.2,
    2390             :            CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
    2391           6 :   CHECK(CompileRun("'flabby' in obj")->BooleanValue(isolate));
    2392          18 :   CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
    2393           6 :   CHECK(CompileRun("'knurd' in obj")->BooleanValue(isolate));
    2394          18 :   CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
    2395             : 
    2396          36 :   CHECK(env->Global()
    2397             :             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
    2398             :                                                    .ToLocalChecked()
    2399             :                                                    ->NewInstance(env.local())
    2400             :                                                    .ToLocalChecked())
    2401             :             .FromJust());
    2402          18 :   CHECK_EQ(17.2,
    2403             :            CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
    2404           6 :   CHECK(CompileRun("'flabby' in obj2")->BooleanValue(isolate));
    2405          18 :   CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
    2406           6 :   CHECK(CompileRun("'knurd' in obj2")->BooleanValue(isolate));
    2407          18 :   CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
    2408             : 
    2409             :   // base1 and base2 cannot cross reference to each's prototype
    2410           6 :   CHECK(CompileRun("obj.v2")->IsUndefined());
    2411          12 :   CHECK(CompileRun("obj2.v1")->IsUndefined());
    2412           6 : }
    2413             : 
    2414       28343 : THREADED_TEST(DescriptorInheritance2) {
    2415           6 :   LocalContext env;
    2416           6 :   v8::Isolate* isolate = CcTest::isolate();
    2417          12 :   v8::HandleScope scope(isolate);
    2418           6 :   v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2419           6 :   fun_A->SetClassName(v8_str("A"));
    2420          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
    2421          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
    2422          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
    2423             : 
    2424           6 :   v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2425           6 :   fun_B->SetClassName(v8_str("B"));
    2426           6 :   fun_B->Inherit(fun_A);
    2427             : 
    2428           6 :   v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
    2429           6 :   fun_C->SetClassName(v8_str("C"));
    2430           6 :   fun_C->Inherit(fun_B);
    2431          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
    2432          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
    2433          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
    2434             : 
    2435           6 :   v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
    2436           6 :   fun_D->SetClassName(v8_str("D"));
    2437           6 :   fun_D->Inherit(fun_C);
    2438             : 
    2439           6 :   v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
    2440           6 :   fun_E->SetClassName(v8_str("E"));
    2441           6 :   fun_E->Inherit(fun_D);
    2442          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
    2443          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
    2444          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
    2445             : 
    2446           6 :   v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
    2447           6 :   fun_F->SetClassName(v8_str("F"));
    2448           6 :   fun_F->Inherit(fun_E);
    2449           6 :   v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
    2450             :   const int kDataPropertiesNumber = 100;
    2451         606 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2452         600 :     v8::Local<v8::Value> val = v8_num(i);
    2453        1200 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2454         600 :     v8::Local<v8::String> name = String::Concat(isolate, v8_str("p"), val_str);
    2455             : 
    2456         600 :     templ->Set(name, val);
    2457         600 :     templ->Set(val_str, val);
    2458             :   }
    2459             : 
    2460          36 :   CHECK(env->Global()
    2461             :             ->Set(env.local(), v8_str("F"),
    2462             :                   fun_F->GetFunction(env.local()).ToLocalChecked())
    2463             :             .FromJust());
    2464             : 
    2465             :   v8::Local<v8::Script> script = v8_compile("o = new F()");
    2466             : 
    2467         606 :   for (int i = 0; i < 100; i++) {
    2468         600 :     v8::HandleScope scope(isolate);
    2469         600 :     script->Run(env.local()).ToLocalChecked();
    2470         600 :   }
    2471           6 :   v8::Local<v8::Object> object = script->Run(env.local())
    2472           6 :                                      .ToLocalChecked()
    2473           6 :                                      ->ToObject(env.local())
    2474           6 :                                      .ToLocalChecked();
    2475             : 
    2476          18 :   CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
    2477          18 :   CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
    2478          18 :   CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
    2479             : 
    2480          18 :   CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
    2481          18 :   CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
    2482          18 :   CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
    2483             : 
    2484          18 :   CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
    2485          18 :   CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
    2486          18 :   CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
    2487             : 
    2488         600 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2489         600 :     v8::Local<v8::Value> val = v8_num(i);
    2490        1800 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2491         600 :     v8::Local<v8::String> name = String::Concat(isolate, v8_str("p"), val_str);
    2492             : 
    2493        2400 :     CHECK_EQ(i, object->Get(env.local(), name)
    2494             :                     .ToLocalChecked()
    2495             :                     ->IntegerValue(env.local())
    2496             :                     .FromJust());
    2497        1800 :     CHECK_EQ(i, object->Get(env.local(), val)
    2498             :                     .ToLocalChecked()
    2499             :                     ->IntegerValue(env.local())
    2500             :                     .FromJust());
    2501           6 :   }
    2502           6 : }
    2503             : 
    2504             : 
    2505             : // Helper functions for Interceptor/Accessor interaction tests
    2506             : 
    2507          36 : void SimpleAccessorGetter(Local<String> name,
    2508             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2509             :   Local<Object> self = Local<Object>::Cast(info.This());
    2510             :   info.GetReturnValue().Set(
    2511             :       self->Get(info.GetIsolate()->GetCurrentContext(),
    2512         144 :                 String::Concat(info.GetIsolate(), v8_str("accessor_"), name))
    2513          36 :           .ToLocalChecked());
    2514          36 : }
    2515             : 
    2516           6 : void SimpleAccessorSetter(Local<String> name, Local<Value> value,
    2517             :                           const v8::PropertyCallbackInfo<void>& info) {
    2518             :   Local<Object> self = Local<Object>::Cast(info.This());
    2519          24 :   CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
    2520             :                   String::Concat(info.GetIsolate(), v8_str("accessor_"), name),
    2521             :                   value)
    2522             :             .FromJust());
    2523           6 : }
    2524             : 
    2525          36 : void SymbolAccessorGetter(Local<Name> name,
    2526             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2527          36 :   CHECK(name->IsSymbol());
    2528             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2529          72 :   if (sym->Name()->IsUndefined())
    2530          36 :     return;
    2531          36 :   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
    2532             : }
    2533             : 
    2534           6 : void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
    2535             :                           const v8::PropertyCallbackInfo<void>& info) {
    2536           6 :   CHECK(name->IsSymbol());
    2537             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2538          12 :   if (sym->Name()->IsUndefined())
    2539           6 :     return;
    2540           6 :   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
    2541             : }
    2542             : 
    2543           5 : void SymbolAccessorGetterReturnsDefault(
    2544             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2545           5 :   CHECK(name->IsSymbol());
    2546             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2547          15 :   if (sym->Name()->IsUndefined()) return;
    2548             :   info.GetReturnValue().Set(info.Data());
    2549             : }
    2550             : 
    2551           5 : static void ThrowingSymbolAccessorGetter(
    2552             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2553          10 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
    2554           5 : }
    2555             : 
    2556             : 
    2557       28343 : THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
    2558           6 :   v8::Isolate* isolate = CcTest::isolate();
    2559           6 :   v8::HandleScope scope(isolate);
    2560          12 :   LocalContext env;
    2561             :   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
    2562             :   i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
    2563          12 :   CHECK_EQ(1, a->map()->instance_descriptors()->number_of_descriptors());
    2564             :   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
    2565          12 :   CHECK_EQ(0, a->map()->instance_descriptors()->number_of_descriptors());
    2566             :   // But we should still have an AccessorInfo.
    2567          12 :   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
    2568             :   i::LookupIterator it(CcTest::i_isolate(), a, name,
    2569           6 :                        i::LookupIterator::OWN_SKIP_INTERCEPTOR);
    2570           6 :   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
    2571          24 :   CHECK(it.GetAccessors()->IsAccessorInfo());
    2572           6 : }
    2573             : 
    2574             : 
    2575       28343 : THREADED_TEST(UndefinedIsNotEnumerable) {
    2576           6 :   LocalContext env;
    2577          12 :   v8::HandleScope scope(env->GetIsolate());
    2578             :   v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
    2579          12 :   CHECK(result->IsFalse());
    2580           6 : }
    2581             : 
    2582             : 
    2583             : v8::Local<Script> call_recursively_script;
    2584             : static const int kTargetRecursionDepth = 100;  // near maximum
    2585             : 
    2586         606 : static void CallScriptRecursivelyCall(
    2587        3012 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2588         606 :   ApiTestFuzzer::Fuzz();
    2589         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2590             :   int depth = args.This()
    2591        1212 :                   ->Get(context, v8_str("depth"))
    2592         606 :                   .ToLocalChecked()
    2593             :                   ->Int32Value(context)
    2594        1212 :                   .FromJust();
    2595         612 :   if (depth == kTargetRecursionDepth) return;
    2596        3000 :   CHECK(args.This()
    2597             :             ->Set(context, v8_str("depth"),
    2598             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2599             :             .FromJust());
    2600             :   args.GetReturnValue().Set(
    2601         600 :       call_recursively_script->Run(context).ToLocalChecked());
    2602             : }
    2603             : 
    2604             : 
    2605         606 : static void CallFunctionRecursivelyCall(
    2606        4212 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2607         606 :   ApiTestFuzzer::Fuzz();
    2608         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2609             :   int depth = args.This()
    2610        1212 :                   ->Get(context, v8_str("depth"))
    2611         606 :                   .ToLocalChecked()
    2612             :                   ->Int32Value(context)
    2613        1212 :                   .FromJust();
    2614         606 :   if (depth == kTargetRecursionDepth) {
    2615             :     printf("[depth = %d]\n", depth);
    2616         612 :     return;
    2617             :   }
    2618        3000 :   CHECK(args.This()
    2619             :             ->Set(context, v8_str("depth"),
    2620             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2621             :             .FromJust());
    2622             :   v8::Local<Value> function =
    2623             :       args.This()
    2624        1200 :           ->Get(context, v8_str("callFunctionRecursively"))
    2625         600 :           .ToLocalChecked();
    2626             :   args.GetReturnValue().Set(function.As<Function>()
    2627         600 :                                 ->Call(context, args.This(), 0, nullptr)
    2628         600 :                                 .ToLocalChecked());
    2629             : }
    2630             : 
    2631             : 
    2632       28343 : THREADED_TEST(DeepCrossLanguageRecursion) {
    2633           6 :   v8::Isolate* isolate = CcTest::isolate();
    2634           6 :   v8::HandleScope scope(isolate);
    2635           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    2636             :   global->Set(v8_str("callScriptRecursively"),
    2637          18 :               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
    2638             :   global->Set(v8_str("callFunctionRecursively"),
    2639          18 :               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
    2640          12 :   LocalContext env(nullptr, global);
    2641             : 
    2642          36 :   CHECK(env->Global()
    2643             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2644             :             .FromJust());
    2645           6 :   call_recursively_script = v8_compile("callScriptRecursively()");
    2646          12 :   call_recursively_script->Run(env.local()).ToLocalChecked();
    2647           6 :   call_recursively_script = v8::Local<Script>();
    2648             : 
    2649          36 :   CHECK(env->Global()
    2650             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2651             :             .FromJust());
    2652           6 :   CompileRun("callFunctionRecursively()");
    2653           6 : }
    2654             : 
    2655             : 
    2656          24 : static void ThrowingPropertyHandlerGet(
    2657             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2658             :   // Since this interceptor is used on "with" objects, the runtime will look up
    2659             :   // @@unscopables.  Punt.
    2660          48 :   if (key->IsSymbol()) return;
    2661          12 :   ApiTestFuzzer::Fuzz();
    2662          24 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
    2663             : }
    2664             : 
    2665             : 
    2666           0 : static void ThrowingPropertyHandlerSet(
    2667             :     Local<Name> key, Local<Value>,
    2668             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2669           0 :   info.GetIsolate()->ThrowException(key);
    2670             :   info.GetReturnValue().SetUndefined();  // not the same as empty handle
    2671           0 : }
    2672             : 
    2673             : 
    2674       28343 : THREADED_TEST(CallbackExceptionRegression) {
    2675           6 :   v8::Isolate* isolate = CcTest::isolate();
    2676           6 :   v8::HandleScope scope(isolate);
    2677           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    2678             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2679           6 :       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
    2680          12 :   LocalContext env;
    2681          36 :   CHECK(env->Global()
    2682             :             ->Set(env.local(), v8_str("obj"),
    2683             :                   obj->NewInstance(env.local()).ToLocalChecked())
    2684             :             .FromJust());
    2685             :   v8::Local<Value> otto =
    2686           6 :       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
    2687          18 :   CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
    2688             :   v8::Local<Value> netto =
    2689           6 :       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
    2690          24 :   CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
    2691           6 : }
    2692             : 
    2693             : 
    2694       28343 : THREADED_TEST(FunctionPrototype) {
    2695           6 :   v8::Isolate* isolate = CcTest::isolate();
    2696           6 :   v8::HandleScope scope(isolate);
    2697           6 :   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
    2698          24 :   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
    2699          12 :   LocalContext env;
    2700          36 :   CHECK(env->Global()
    2701             :             ->Set(env.local(), v8_str("Foo"),
    2702             :                   Foo->GetFunction(env.local()).ToLocalChecked())
    2703             :             .FromJust());
    2704           6 :   Local<Script> script = v8_compile("Foo.prototype.plak");
    2705          12 :   CHECK_EQ(v8_run_int32value(script), 321);
    2706           6 : }
    2707             : 
    2708       28343 : THREADED_TEST(InternalFields) {
    2709           6 :   LocalContext env;
    2710           6 :   v8::Isolate* isolate = env->GetIsolate();
    2711          12 :   v8::HandleScope scope(isolate);
    2712             : 
    2713           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2714           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2715           6 :   instance_templ->SetInternalFieldCount(1);
    2716           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2717           6 :                               .ToLocalChecked()
    2718           6 :                               ->NewInstance(env.local())
    2719             :                               .ToLocalChecked();
    2720           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2721           6 :   CHECK(obj->GetInternalField(0)->IsUndefined());
    2722           6 :   obj->SetInternalField(0, v8_num(17));
    2723          24 :   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2724           6 : }
    2725             : 
    2726       28342 : TEST(InternalFieldsSubclassing) {
    2727           5 :   LocalContext env;
    2728           5 :   v8::Isolate* isolate = env->GetIsolate();
    2729             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    2730          10 :   v8::HandleScope scope(isolate);
    2731          65 :   for (int nof_embedder_fields = 0;
    2732             :        nof_embedder_fields < i::JSObject::kMaxEmbedderFields;
    2733             :        nof_embedder_fields++) {
    2734          60 :     Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2735          60 :     Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2736          60 :     instance_templ->SetInternalFieldCount(nof_embedder_fields);
    2737             :     Local<Function> constructor =
    2738          60 :         templ->GetFunction(env.local()).ToLocalChecked();
    2739             :     // Check that instances have the correct NOF properties.
    2740             :     Local<v8::Object> obj =
    2741          60 :         constructor->NewInstance(env.local()).ToLocalChecked();
    2742             : 
    2743             :     i::Handle<i::JSObject> i_obj =
    2744          60 :         i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj));
    2745          60 :     CHECK_EQ(nof_embedder_fields, obj->InternalFieldCount());
    2746          60 :     CHECK_EQ(0, i_obj->map()->GetInObjectProperties());
    2747             :     // Check writing and reading internal fields.
    2748         330 :     for (int j = 0; j < nof_embedder_fields; j++) {
    2749         330 :       CHECK(obj->GetInternalField(j)->IsUndefined());
    2750         330 :       int value = 17 + j;
    2751         330 :       obj->SetInternalField(j, v8_num(value));
    2752             :     }
    2753         330 :     for (int j = 0; j < nof_embedder_fields; j++) {
    2754         330 :       int value = 17 + j;
    2755         990 :       CHECK_EQ(value,
    2756             :                obj->GetInternalField(j)->Int32Value(env.local()).FromJust());
    2757             :     }
    2758         300 :     CHECK(env->Global()
    2759             :               ->Set(env.local(), v8_str("BaseClass"), constructor)
    2760             :               .FromJust());
    2761             :     // Create various levels of subclasses to stress instance size calculation.
    2762             :     const int kMaxNofProperties =
    2763             :         i::JSObject::kMaxInObjectProperties -
    2764          60 :         nof_embedder_fields * i::kEmbedderDataSlotSizeInTaggedSlots;
    2765             :     // Select only a few values to speed up the test.
    2766             :     int sizes[] = {0,
    2767             :                    1,
    2768             :                    2,
    2769             :                    3,
    2770             :                    4,
    2771             :                    5,
    2772             :                    6,
    2773          60 :                    kMaxNofProperties / 4,
    2774          60 :                    kMaxNofProperties / 2,
    2775          60 :                    kMaxNofProperties - 2,
    2776          60 :                    kMaxNofProperties - 1,
    2777          60 :                    kMaxNofProperties + 1,
    2778          60 :                    kMaxNofProperties + 2,
    2779          60 :                    kMaxNofProperties * 2,
    2780         480 :                    kMaxNofProperties * 2};
    2781         960 :     for (size_t i = 0; i < arraysize(sizes); i++) {
    2782         900 :       int nof_properties = sizes[i];
    2783         900 :       bool in_object_only = nof_properties <= kMaxNofProperties;
    2784         900 :       std::ostringstream src;
    2785             :       // Assembler source string for a subclass with {nof_properties}
    2786             :       // in-object properties.
    2787         900 :       src << "(function() {\n"
    2788         900 :           << "  class SubClass extends BaseClass {\n"
    2789         900 :           << "    constructor() {\n"
    2790         900 :           << "      super();\n";
    2791             :       // Set {nof_properties} instance properties in the constructor.
    2792      131535 :       for (int j = 0; j < nof_properties; j++) {
    2793      130635 :         src << "      this.property" << j << " = " << j << ";\n";
    2794             :       }
    2795         900 :       src << "    }\n"
    2796         900 :           << "  };\n"
    2797         900 :           << "  let instance;\n"
    2798         900 :           << "  for (let i = 0; i < 3; i++) {\n"
    2799         900 :           << "    instance = new SubClass();\n"
    2800         900 :           << "  }"
    2801         900 :           << "  return instance;\n"
    2802         900 :           << "})();";
    2803         900 :       Local<v8::Object> value = CompileRun(src.str().c_str()).As<v8::Object>();
    2804             : 
    2805             :       i::Handle<i::JSObject> i_value =
    2806         900 :           i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*value));
    2807             : #ifdef VERIFY_HEAP
    2808             :       i_value->HeapObjectVerify(i_isolate);
    2809             :       i_value->map()->HeapObjectVerify(i_isolate);
    2810             :       i_value->map()->FindRootMap(i_isolate)->HeapObjectVerify(i_isolate);
    2811             : #endif
    2812         900 :       CHECK_EQ(nof_embedder_fields, value->InternalFieldCount());
    2813         900 :       if (in_object_only) {
    2814         660 :         CHECK_LE(nof_properties, i_value->map()->GetInObjectProperties());
    2815             :       } else {
    2816         240 :         CHECK_LE(kMaxNofProperties, i_value->map()->GetInObjectProperties());
    2817             :       }
    2818             : 
    2819             :       // Make Sure we get the precise property count.
    2820        1800 :       i_value->map()->FindRootMap(i_isolate)->CompleteInobjectSlackTracking(
    2821         900 :           i_isolate);
    2822             :       // TODO(cbruni): fix accounting to make this condition true.
    2823             :       // CHECK_EQ(0, i_value->map()->UnusedPropertyFields());
    2824         900 :       if (in_object_only) {
    2825         660 :         CHECK_EQ(nof_properties, i_value->map()->GetInObjectProperties());
    2826             :       } else {
    2827         240 :         CHECK_LE(kMaxNofProperties, i_value->map()->GetInObjectProperties());
    2828             :       }
    2829         900 :     }
    2830           5 :   }
    2831           5 : }
    2832             : 
    2833       28343 : THREADED_TEST(InternalFieldsOfRegularObjects) {
    2834           6 :   LocalContext env;
    2835           6 :   v8::Isolate* isolate = env->GetIsolate();
    2836          12 :   v8::HandleScope scope(isolate);
    2837             : 
    2838           6 :   const char* sources[] = {"new Object()", "{ a: 'a property' }", "arguments"};
    2839          24 :   for (size_t i = 0; i < arraysize(sources); ++i) {
    2840             :     i::ScopedVector<char> source(128);
    2841          18 :     i::SNPrintF(source, "(function() { return %s })()", sources[i]);
    2842             :     v8::Local<v8::Object> obj = CompileRun(source.start()).As<v8::Object>();
    2843          18 :     CHECK_EQ(0, obj->InternalFieldCount());
    2844           6 :   }
    2845           6 : }
    2846             : 
    2847       28343 : THREADED_TEST(GlobalObjectInternalFields) {
    2848           6 :   v8::Isolate* isolate = CcTest::isolate();
    2849           6 :   v8::HandleScope scope(isolate);
    2850           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
    2851           6 :   global_template->SetInternalFieldCount(1);
    2852          12 :   LocalContext env(nullptr, global_template);
    2853           6 :   v8::Local<v8::Object> global_proxy = env->Global();
    2854           6 :   v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
    2855           6 :   CHECK_EQ(1, global->InternalFieldCount());
    2856           6 :   CHECK(global->GetInternalField(0)->IsUndefined());
    2857           6 :   global->SetInternalField(0, v8_num(17));
    2858          24 :   CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2859           6 : }
    2860             : 
    2861             : 
    2862       28343 : THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
    2863           6 :   LocalContext env;
    2864          12 :   v8::HandleScope scope(CcTest::isolate());
    2865             : 
    2866           6 :   v8::Local<v8::Object> global = env->Global();
    2867          18 :   CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
    2868          18 :   CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
    2869           6 : }
    2870             : 
    2871          24 : static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
    2872             :                                                void* value) {
    2873          24 :   CHECK(HAS_SMI_TAG(reinterpret_cast<i::Address>(value)));
    2874          24 :   obj->SetAlignedPointerInInternalField(0, value);
    2875          24 :   CcTest::CollectAllGarbage();
    2876          24 :   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
    2877          24 : }
    2878             : 
    2879       28343 : THREADED_TEST(InternalFieldsAlignedPointers) {
    2880           6 :   LocalContext env;
    2881           6 :   v8::Isolate* isolate = env->GetIsolate();
    2882          12 :   v8::HandleScope scope(isolate);
    2883             : 
    2884           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2885           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2886           6 :   instance_templ->SetInternalFieldCount(1);
    2887           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2888           6 :                               .ToLocalChecked()
    2889           6 :                               ->NewInstance(env.local())
    2890             :                               .ToLocalChecked();
    2891           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2892             : 
    2893           6 :   CheckAlignedPointerInInternalField(obj, nullptr);
    2894             : 
    2895           6 :   int* heap_allocated = new int[100];
    2896           6 :   CheckAlignedPointerInInternalField(obj, heap_allocated);
    2897           6 :   delete[] heap_allocated;
    2898             : 
    2899             :   int stack_allocated[100];
    2900           6 :   CheckAlignedPointerInInternalField(obj, stack_allocated);
    2901             : 
    2902             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2903           6 :   CheckAlignedPointerInInternalField(obj, huge);
    2904             : 
    2905             :   v8::Global<v8::Object> persistent(isolate, obj);
    2906           6 :   CHECK_EQ(1, Object::InternalFieldCount(persistent));
    2907          12 :   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
    2908           6 : }
    2909             : 
    2910       28343 : THREADED_TEST(SetAlignedPointerInInternalFields) {
    2911           6 :   LocalContext env;
    2912           6 :   v8::Isolate* isolate = env->GetIsolate();
    2913          12 :   v8::HandleScope scope(isolate);
    2914             : 
    2915           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2916           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2917           6 :   instance_templ->SetInternalFieldCount(2);
    2918           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2919           6 :                               .ToLocalChecked()
    2920           6 :                               ->NewInstance(env.local())
    2921             :                               .ToLocalChecked();
    2922           6 :   CHECK_EQ(2, obj->InternalFieldCount());
    2923             : 
    2924           6 :   int* heap_allocated_1 = new int[100];
    2925           6 :   int* heap_allocated_2 = new int[100];
    2926           6 :   int indices[] = {0, 1};
    2927           6 :   void* values[] = {heap_allocated_1, heap_allocated_2};
    2928             : 
    2929           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2930           6 :   CcTest::CollectAllGarbage();
    2931           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(0));
    2932           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(1));
    2933             : 
    2934           6 :   indices[0] = 1;
    2935           6 :   indices[1] = 0;
    2936           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2937           6 :   CcTest::CollectAllGarbage();
    2938           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(0));
    2939           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(1));
    2940             : 
    2941           6 :   delete[] heap_allocated_1;
    2942          12 :   delete[] heap_allocated_2;
    2943           6 : }
    2944             : 
    2945          24 : static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
    2946             :                                               void* value) {
    2947          24 :   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
    2948          24 :   (*env)->SetAlignedPointerInEmbedderData(index, value);
    2949          24 :   CcTest::CollectAllGarbage();
    2950          24 :   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
    2951          24 : }
    2952             : 
    2953             : 
    2954             : static void* AlignedTestPointer(int i) {
    2955        1200 :   return reinterpret_cast<void*>(i * 1234);
    2956             : }
    2957             : 
    2958             : 
    2959       28343 : THREADED_TEST(EmbedderDataAlignedPointers) {
    2960           6 :   LocalContext env;
    2961          12 :   v8::HandleScope scope(env->GetIsolate());
    2962             : 
    2963           6 :   CheckAlignedPointerInEmbedderData(&env, 0, nullptr);
    2964           6 :   CHECK_EQ(1, (*env)->GetNumberOfEmbedderDataFields());
    2965             : 
    2966           6 :   int* heap_allocated = new int[100];
    2967           6 :   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
    2968           6 :   CHECK_EQ(2, (*env)->GetNumberOfEmbedderDataFields());
    2969           6 :   delete[] heap_allocated;
    2970             : 
    2971             :   int stack_allocated[100];
    2972           6 :   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
    2973           6 :   CHECK_EQ(3, (*env)->GetNumberOfEmbedderDataFields());
    2974             : 
    2975             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2976           6 :   CheckAlignedPointerInEmbedderData(&env, 3, huge);
    2977           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    2978             : 
    2979             :   // Test growing of the embedder data's backing store.
    2980         600 :   for (int i = 0; i < 100; i++) {
    2981         600 :     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
    2982             :   }
    2983           6 :   CcTest::CollectAllGarbage();
    2984         606 :   for (int i = 0; i < 100; i++) {
    2985         600 :     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
    2986           6 :   }
    2987           6 : }
    2988             : 
    2989          30 : static void CheckEmbedderData(LocalContext* env, int index,
    2990             :                               v8::Local<Value> data) {
    2991          30 :   (*env)->SetEmbedderData(index, data);
    2992          30 :   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
    2993          30 : }
    2994             : 
    2995             : 
    2996       28343 : THREADED_TEST(EmbedderData) {
    2997           6 :   LocalContext env;
    2998           6 :   v8::Isolate* isolate = env->GetIsolate();
    2999          12 :   v8::HandleScope scope(isolate);
    3000             : 
    3001           6 :   CHECK_EQ(0, (*env)->GetNumberOfEmbedderDataFields());
    3002          12 :   CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
    3003           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3004          12 :   CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
    3005           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3006          12 :   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
    3007           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3008           6 :   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
    3009           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3010           6 :   CheckEmbedderData(&env, 211, v8::Boolean::New(isolate, true));
    3011          12 :   CHECK_EQ(212, (*env)->GetNumberOfEmbedderDataFields());
    3012           6 : }
    3013             : 
    3014             : 
    3015       28343 : THREADED_TEST(IdentityHash) {
    3016           6 :   LocalContext env;
    3017           6 :   v8::Isolate* isolate = env->GetIsolate();
    3018          12 :   v8::HandleScope scope(isolate);
    3019             : 
    3020             :   // Ensure that the test starts with an fresh heap to test whether the hash
    3021             :   // code is based on the address.
    3022           6 :   CcTest::CollectAllGarbage();
    3023           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
    3024           6 :   int hash = obj->GetIdentityHash();
    3025           6 :   int hash1 = obj->GetIdentityHash();
    3026           6 :   CHECK_EQ(hash, hash1);
    3027          12 :   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
    3028             :   // Since the identity hash is essentially a random number two consecutive
    3029             :   // objects should not be assigned the same hash code. If the test below fails
    3030             :   // the random number generator should be evaluated.
    3031           6 :   CHECK_NE(hash, hash2);
    3032           6 :   CcTest::CollectAllGarbage();
    3033          12 :   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
    3034             :   // Make sure that the identity hash is not based on the initial address of
    3035             :   // the object alone. If the test below fails the random number generator
    3036             :   // should be evaluated.
    3037           6 :   CHECK_NE(hash, hash3);
    3038           6 :   int hash4 = obj->GetIdentityHash();
    3039           6 :   CHECK_EQ(hash, hash4);
    3040             : 
    3041             :   // Check identity hashes behaviour in the presence of JS accessors.
    3042             :   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
    3043             :   {
    3044             :     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
    3045           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    3046           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    3047          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    3048             :   }
    3049             :   {
    3050             :     CompileRun(
    3051             :         "function cnst() { return 42; };\n"
    3052             :         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
    3053           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    3054           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    3055          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    3056           6 :   }
    3057           6 : }
    3058             : 
    3059             : 
    3060          12 : void GlobalProxyIdentityHash(bool set_in_js) {
    3061          12 :   LocalContext env;
    3062          12 :   v8::Isolate* isolate = env->GetIsolate();
    3063             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    3064          24 :   v8::HandleScope scope(isolate);
    3065          12 :   Local<Object> global_proxy = env->Global();
    3066             :   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
    3067          60 :   CHECK(env->Global()
    3068             :             ->Set(env.local(), v8_str("global"), global_proxy)
    3069             :             .FromJust());
    3070             :   int32_t hash1;
    3071          12 :   if (set_in_js) {
    3072             :     CompileRun("var m = new Set(); m.add(global);");
    3073           6 :     i::Object original_hash = i_global_proxy->GetHash();
    3074           6 :     CHECK(original_hash->IsSmi());
    3075           6 :     hash1 = i::Smi::ToInt(original_hash);
    3076             :   } else {
    3077          12 :     hash1 = i_global_proxy->GetOrCreateHash(i_isolate)->value();
    3078             :   }
    3079             :   // Hash should be retained after being detached.
    3080          12 :   env->DetachGlobal();
    3081          12 :   int hash2 = global_proxy->GetIdentityHash();
    3082          12 :   CHECK_EQ(hash1, hash2);
    3083             :   {
    3084             :     // Re-attach global proxy to a new context, hash should stay the same.
    3085          12 :     LocalContext env2(nullptr, Local<ObjectTemplate>(), global_proxy);
    3086          12 :     int hash3 = global_proxy->GetIdentityHash();
    3087          12 :     CHECK_EQ(hash1, hash3);
    3088          12 :   }
    3089          12 : }
    3090             : 
    3091             : 
    3092       28343 : THREADED_TEST(GlobalProxyIdentityHash) {
    3093           6 :   GlobalProxyIdentityHash(true);
    3094           6 :   GlobalProxyIdentityHash(false);
    3095           6 : }
    3096             : 
    3097             : 
    3098       28342 : TEST(SymbolIdentityHash) {
    3099           5 :   LocalContext env;
    3100           5 :   v8::Isolate* isolate = env->GetIsolate();
    3101          10 :   v8::HandleScope scope(isolate);
    3102             : 
    3103             :   {
    3104           5 :     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
    3105           5 :     int hash = symbol->GetIdentityHash();
    3106           5 :     int hash1 = symbol->GetIdentityHash();
    3107           5 :     CHECK_EQ(hash, hash1);
    3108           5 :     CcTest::CollectAllGarbage();
    3109           5 :     int hash3 = symbol->GetIdentityHash();
    3110           5 :     CHECK_EQ(hash, hash3);
    3111             :   }
    3112             : 
    3113             :   {
    3114             :     v8::Local<v8::Symbol> js_symbol =
    3115             :         CompileRun("Symbol('foo')").As<v8::Symbol>();
    3116           5 :     int hash = js_symbol->GetIdentityHash();
    3117           5 :     int hash1 = js_symbol->GetIdentityHash();
    3118           5 :     CHECK_EQ(hash, hash1);
    3119           5 :     CcTest::CollectAllGarbage();
    3120           5 :     int hash3 = js_symbol->GetIdentityHash();
    3121           5 :     CHECK_EQ(hash, hash3);
    3122           5 :   }
    3123           5 : }
    3124             : 
    3125             : 
    3126       28342 : TEST(StringIdentityHash) {
    3127           5 :   LocalContext env;
    3128           5 :   v8::Isolate* isolate = env->GetIsolate();
    3129          10 :   v8::HandleScope scope(isolate);
    3130             : 
    3131           5 :   Local<v8::String> str = v8_str("str1");
    3132           5 :   int hash = str->GetIdentityHash();
    3133           5 :   int hash1 = str->GetIdentityHash();
    3134           5 :   CHECK_EQ(hash, hash1);
    3135           5 :   CcTest::CollectAllGarbage();
    3136           5 :   int hash3 = str->GetIdentityHash();
    3137           5 :   CHECK_EQ(hash, hash3);
    3138             : 
    3139           5 :   Local<v8::String> str2 = v8_str("str1");
    3140           5 :   int hash4 = str2->GetIdentityHash();
    3141          10 :   CHECK_EQ(hash, hash4);
    3142           5 : }
    3143             : 
    3144             : 
    3145       28343 : THREADED_TEST(SymbolProperties) {
    3146           6 :   LocalContext env;
    3147           6 :   v8::Isolate* isolate = env->GetIsolate();
    3148          12 :   v8::HandleScope scope(isolate);
    3149             : 
    3150           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3151           6 :   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
    3152           6 :   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
    3153           6 :   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
    3154           6 :   v8::Local<v8::Symbol> sym4 = v8::Symbol::New(isolate, v8_str("native"));
    3155             : 
    3156           6 :   CcTest::CollectAllGarbage();
    3157             : 
    3158             :   // Check basic symbol functionality.
    3159           6 :   CHECK(sym1->IsSymbol());
    3160           6 :   CHECK(sym2->IsSymbol());
    3161           6 :   CHECK(!obj->IsSymbol());
    3162             : 
    3163          12 :   CHECK(sym1->Equals(env.local(), sym1).FromJust());
    3164          12 :   CHECK(sym2->Equals(env.local(), sym2).FromJust());
    3165          12 :   CHECK(!sym1->Equals(env.local(), sym2).FromJust());
    3166          12 :   CHECK(!sym2->Equals(env.local(), sym1).FromJust());
    3167           6 :   CHECK(sym1->StrictEquals(sym1));
    3168           6 :   CHECK(sym2->StrictEquals(sym2));
    3169           6 :   CHECK(!sym1->StrictEquals(sym2));
    3170           6 :   CHECK(!sym2->StrictEquals(sym1));
    3171             : 
    3172          24 :   CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
    3173             : 
    3174             :   v8::Local<v8::Value> sym_val = sym2;
    3175           6 :   CHECK(sym_val->IsSymbol());
    3176          12 :   CHECK(sym_val->Equals(env.local(), sym2).FromJust());
    3177           6 :   CHECK(sym_val->StrictEquals(sym2));
    3178          12 :   CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
    3179             : 
    3180           6 :   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
    3181           6 :   CHECK(sym_obj->IsSymbolObject());
    3182           6 :   CHECK(!sym2->IsSymbolObject());
    3183           6 :   CHECK(!obj->IsSymbolObject());
    3184          12 :   CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
    3185           6 :   CHECK(!sym_obj->StrictEquals(sym2));
    3186          12 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3187             :             ->Equals(env.local(), sym_obj)
    3188             :             .FromJust());
    3189          18 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3190             :             ->ValueOf()
    3191             :             ->Equals(env.local(), sym2)
    3192             :             .FromJust());
    3193             : 
    3194             :   // Make sure delete of a non-existent symbol property works.
    3195          12 :   CHECK(obj->Delete(env.local(), sym1).FromJust());
    3196          12 :   CHECK(!obj->Has(env.local(), sym1).FromJust());
    3197             : 
    3198          18 :   CHECK(
    3199             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
    3200          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3201          24 :   CHECK_EQ(1503, obj->Get(env.local(), sym1)
    3202             :                      .ToLocalChecked()
    3203             :                      ->Int32Value(env.local())
    3204             :                      .FromJust());
    3205          18 :   CHECK(
    3206             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
    3207          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3208          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3209             :                      .ToLocalChecked()
    3210             :                      ->Int32Value(env.local())
    3211             :                      .FromJust());
    3212          12 :   CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
    3213             : 
    3214          12 :   CHECK_EQ(0u,
    3215             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3216             :   unsigned num_props =
    3217          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3218          24 :   CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
    3219             :             .FromJust());
    3220          12 :   CHECK_EQ(1u,
    3221             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3222          12 :   CHECK_EQ(num_props + 1,
    3223             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3224             : 
    3225           6 :   CcTest::CollectAllGarbage();
    3226             : 
    3227          12 :   CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
    3228             :                          SymbolAccessorSetter)
    3229             :             .FromJust());
    3230          12 :   CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
    3231          18 :   CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
    3232          30 :   CHECK(obj->Get(env.local(), sym3)
    3233             :             .ToLocalChecked()
    3234             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3235             :             .FromJust());
    3236          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3237             :             .ToLocalChecked()
    3238             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3239             :             .FromJust());
    3240             : 
    3241          12 :   CHECK(obj->SetNativeDataProperty(env.local(), sym4, SymbolAccessorGetter)
    3242             :             .FromJust());
    3243          12 :   CHECK(obj->Get(env.local(), sym4).ToLocalChecked()->IsUndefined());
    3244          24 :   CHECK(obj->Set(env.local(), v8_str("accessor_native"),
    3245             :                  v8::Integer::New(isolate, 123))
    3246             :             .FromJust());
    3247          24 :   CHECK_EQ(123, obj->Get(env.local(), sym4)
    3248             :                     .ToLocalChecked()
    3249             :                     ->Int32Value(env.local())
    3250             :                     .FromJust());
    3251          18 :   CHECK(obj->Set(env.local(), sym4, v8::Integer::New(isolate, 314)).FromJust());
    3252          30 :   CHECK(obj->Get(env.local(), sym4)
    3253             :             .ToLocalChecked()
    3254             :             ->Equals(env.local(), v8::Integer::New(isolate, 314))
    3255             :             .FromJust());
    3256          18 :   CHECK(obj->Delete(env.local(), v8_str("accessor_native")).FromJust());
    3257             : 
    3258             :   // Add another property and delete it afterwards to force the object in
    3259             :   // slow case.
    3260          18 :   CHECK(
    3261             :       obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
    3262          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3263             :                      .ToLocalChecked()
    3264             :                      ->Int32Value(env.local())
    3265             :                      .FromJust());
    3266          24 :   CHECK_EQ(2008, obj->Get(env.local(), sym2)
    3267             :                      .ToLocalChecked()
    3268             :                      ->Int32Value(env.local())
    3269             :                      .FromJust());
    3270          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3271             :                      .ToLocalChecked()
    3272             :                      ->Int32Value(env.local())
    3273             :                      .FromJust());
    3274          12 :   CHECK_EQ(2u,
    3275             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3276             : 
    3277          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3278          12 :   CHECK(obj->Has(env.local(), sym2).FromJust());
    3279          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3280          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3281          12 :   CHECK(obj->Delete(env.local(), sym2).FromJust());
    3282          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3283          12 :   CHECK(!obj->Has(env.local(), sym2).FromJust());
    3284          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3285          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3286          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3287             :                      .ToLocalChecked()
    3288             :                      ->Int32Value(env.local())
    3289             :                      .FromJust());
    3290          30 :   CHECK(obj->Get(env.local(), sym3)
    3291             :             .ToLocalChecked()
    3292             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3293             :             .FromJust());
    3294          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3295             :             .ToLocalChecked()
    3296             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3297             :             .FromJust());
    3298          12 :   CHECK_EQ(2u,
    3299             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3300             : 
    3301             :   // Symbol properties are inherited.
    3302           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3303          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3304          12 :   CHECK(child->Has(env.local(), sym1).FromJust());
    3305          24 :   CHECK_EQ(2002, child->Get(env.local(), sym1)
    3306             :                      .ToLocalChecked()
    3307             :                      ->Int32Value(env.local())
    3308             :                      .FromJust());
    3309          30 :   CHECK(obj->Get(env.local(), sym3)
    3310             :             .ToLocalChecked()
    3311             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3312             :             .FromJust());
    3313          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3314             :             .ToLocalChecked()
    3315             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3316             :             .FromJust());
    3317          12 :   CHECK_EQ(0u,
    3318           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3319           6 : }
    3320             : 
    3321             : 
    3322       28343 : THREADED_TEST(SymbolTemplateProperties) {
    3323           6 :   LocalContext env;
    3324           6 :   v8::Isolate* isolate = env->GetIsolate();
    3325          12 :   v8::HandleScope scope(isolate);
    3326           6 :   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
    3327           6 :   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
    3328           6 :   CHECK(!name.IsEmpty());
    3329          18 :   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
    3330             :   v8::Local<v8::Object> new_instance =
    3331          18 :       foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    3332           6 :   CHECK(!new_instance.IsEmpty());
    3333          18 :   CHECK(new_instance->Has(env.local(), name).FromJust());
    3334           6 : }
    3335             : 
    3336             : 
    3337       28343 : THREADED_TEST(PrivatePropertiesOnProxies) {
    3338           6 :   LocalContext env;
    3339           6 :   v8::Isolate* isolate = env->GetIsolate();
    3340          12 :   v8::HandleScope scope(isolate);
    3341             : 
    3342           6 :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
    3343           6 :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
    3344             : 
    3345             :   v8::Local<v8::Proxy> proxy =
    3346           6 :       v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
    3347             : 
    3348           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3349             :   v8::Local<v8::Private> priv2 =
    3350           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3351             : 
    3352           6 :   CcTest::CollectAllGarbage();
    3353             : 
    3354          30 :   CHECK(priv2->Name()
    3355             :             ->Equals(env.local(),
    3356             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3357             :                                              v8::NewStringType::kNormal)
    3358             :                          .ToLocalChecked())
    3359             :             .FromJust());
    3360             : 
    3361             :   // Make sure delete of a non-existent private symbol property works.
    3362          12 :   proxy->DeletePrivate(env.local(), priv1).FromJust();
    3363          12 :   CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
    3364             : 
    3365          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3366             :             .FromJust());
    3367          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3368          18 :   CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
    3369             :                      .ToLocalChecked()
    3370             :                      ->Int32Value(env.local())
    3371             :                      .FromJust());
    3372          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3373             :             .FromJust());
    3374          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3375          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3376             :                      .ToLocalChecked()
    3377             :                      ->Int32Value(env.local())
    3378             :                      .FromJust());
    3379             : 
    3380          12 :   CHECK_EQ(0u,
    3381             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3382             :   unsigned num_props =
    3383          12 :       proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3384          24 :   CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
    3385             :                                     isolate, "bla", v8::NewStringType::kNormal)
    3386             :                                     .ToLocalChecked(),
    3387             :                    v8::Integer::New(isolate, 20))
    3388             :             .FromJust());
    3389          12 :   CHECK_EQ(1u,
    3390             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3391          12 :   CHECK_EQ(num_props + 1,
    3392             :            proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3393             : 
    3394           6 :   CcTest::CollectAllGarbage();
    3395             : 
    3396             :   // Add another property and delete it afterwards to force the object in
    3397             :   // slow case.
    3398          18 :   CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3399             :             .FromJust());
    3400          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3401             :                      .ToLocalChecked()
    3402             :                      ->Int32Value(env.local())
    3403             :                      .FromJust());
    3404          18 :   CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
    3405             :                      .ToLocalChecked()
    3406             :                      ->Int32Value(env.local())
    3407             :                      .FromJust());
    3408          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3409             :                      .ToLocalChecked()
    3410             :                      ->Int32Value(env.local())
    3411             :                      .FromJust());
    3412          12 :   CHECK_EQ(1u,
    3413             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3414             : 
    3415          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3416          12 :   CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
    3417          12 :   CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
    3418          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3419          12 :   CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
    3420          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3421             :                      .ToLocalChecked()
    3422             :                      ->Int32Value(env.local())
    3423             :                      .FromJust());
    3424          12 :   CHECK_EQ(1u,
    3425             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3426             : 
    3427             :   // Private properties are not inherited (for the time being).
    3428           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3429          12 :   CHECK(child->SetPrototype(env.local(), proxy).FromJust());
    3430          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3431          12 :   CHECK_EQ(0u,
    3432           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3433           6 : }
    3434             : 
    3435             : 
    3436       28343 : THREADED_TEST(PrivateProperties) {
    3437           6 :   LocalContext env;
    3438           6 :   v8::Isolate* isolate = env->GetIsolate();
    3439          12 :   v8::HandleScope scope(isolate);
    3440             : 
    3441           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3442           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3443             :   v8::Local<v8::Private> priv2 =
    3444           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3445             : 
    3446           6 :   CcTest::CollectAllGarbage();
    3447             : 
    3448          30 :   CHECK(priv2->Name()
    3449             :             ->Equals(env.local(),
    3450             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3451             :                                              v8::NewStringType::kNormal)
    3452             :                          .ToLocalChecked())
    3453             :             .FromJust());
    3454             : 
    3455             :   // Make sure delete of a non-existent private symbol property works.
    3456          12 :   obj->DeletePrivate(env.local(), priv1).FromJust();
    3457          12 :   CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
    3458             : 
    3459          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3460             :             .FromJust());
    3461          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3462          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
    3463             :                      .ToLocalChecked()
    3464             :                      ->Int32Value(env.local())
    3465             :                      .FromJust());
    3466          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3467             :             .FromJust());
    3468          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3469          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3470             :                      .ToLocalChecked()
    3471             :                      ->Int32Value(env.local())
    3472             :                      .FromJust());
    3473             : 
    3474          12 :   CHECK_EQ(0u,
    3475             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3476             :   unsigned num_props =
    3477          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3478          24 :   CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
    3479             :                                   isolate, "bla", v8::NewStringType::kNormal)
    3480             :                                   .ToLocalChecked(),
    3481             :                  v8::Integer::New(isolate, 20))
    3482             :             .FromJust());
    3483          12 :   CHECK_EQ(1u,
    3484             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3485          12 :   CHECK_EQ(num_props + 1,
    3486             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3487             : 
    3488           6 :   CcTest::CollectAllGarbage();
    3489             : 
    3490             :   // Add another property and delete it afterwards to force the object in
    3491             :   // slow case.
    3492          18 :   CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3493             :             .FromJust());
    3494          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3495             :                      .ToLocalChecked()
    3496             :                      ->Int32Value(env.local())
    3497             :                      .FromJust());
    3498          18 :   CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
    3499             :                      .ToLocalChecked()
    3500             :                      ->Int32Value(env.local())
    3501             :                      .FromJust());
    3502          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3503             :                      .ToLocalChecked()
    3504             :                      ->Int32Value(env.local())
    3505             :                      .FromJust());
    3506          12 :   CHECK_EQ(1u,
    3507             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3508             : 
    3509          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3510          12 :   CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
    3511          12 :   CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
    3512          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3513          12 :   CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
    3514          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3515             :                      .ToLocalChecked()
    3516             :                      ->Int32Value(env.local())
    3517             :                      .FromJust());
    3518          12 :   CHECK_EQ(1u,
    3519             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3520             : 
    3521             :   // Private properties are not inherited (for the time being).
    3522           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3523          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3524          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3525          12 :   CHECK_EQ(0u,
    3526           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3527           6 : }
    3528             : 
    3529             : 
    3530       28343 : THREADED_TEST(GlobalSymbols) {
    3531           6 :   LocalContext env;
    3532           6 :   v8::Isolate* isolate = env->GetIsolate();
    3533          12 :   v8::HandleScope scope(isolate);
    3534             : 
    3535           6 :   v8::Local<String> name = v8_str("my-symbol");
    3536           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3537           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3538           6 :   CHECK(glob2->SameValue(glob));
    3539             : 
    3540           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3541           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3542           6 :   CHECK(glob_api2->SameValue(glob_api));
    3543           6 :   CHECK(!glob_api->SameValue(glob));
    3544             : 
    3545           6 :   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
    3546           6 :   CHECK(!sym->SameValue(glob));
    3547             : 
    3548             :   CompileRun("var sym2 = Symbol.for('my-symbol')");
    3549             :   v8::Local<Value> sym2 =
    3550          30 :       env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
    3551           6 :   CHECK(sym2->SameValue(glob));
    3552          12 :   CHECK(!sym2->SameValue(glob_api));
    3553           6 : }
    3554             : 
    3555       28343 : THREADED_TEST(GlobalSymbolsNoContext) {
    3556           6 :   v8::Isolate* isolate = CcTest::isolate();
    3557           6 :   v8::HandleScope scope(isolate);
    3558             : 
    3559           6 :   v8::Local<String> name = v8_str("my-symbol");
    3560           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3561           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3562           6 :   CHECK(glob2->SameValue(glob));
    3563             : 
    3564           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3565           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3566           6 :   CHECK(glob_api2->SameValue(glob_api));
    3567           6 :   CHECK(!glob_api->SameValue(glob));
    3568           6 : }
    3569             : 
    3570          60 : static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
    3571             :                                  const char* name) {
    3572          60 :   LocalContext env;
    3573          60 :   v8::Isolate* isolate = env->GetIsolate();
    3574         120 :   v8::HandleScope scope(isolate);
    3575             : 
    3576          60 :   v8::Local<v8::Symbol> symbol = getter(isolate);
    3577         120 :   std::string script = std::string("var sym = ") + name;
    3578             :   CompileRun(script.c_str());
    3579             :   v8::Local<Value> value =
    3580         300 :       env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
    3581             : 
    3582          60 :   CHECK(!value.IsEmpty());
    3583          60 :   CHECK(!symbol.IsEmpty());
    3584         120 :   CHECK(value->SameValue(symbol));
    3585          60 : }
    3586             : 
    3587             : 
    3588       28343 : THREADED_TEST(WellKnownSymbols) {
    3589           6 :   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
    3590           6 :   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
    3591           6 :   CheckWellKnownSymbol(v8::Symbol::GetHasInstance, "Symbol.hasInstance");
    3592             :   CheckWellKnownSymbol(v8::Symbol::GetIsConcatSpreadable,
    3593           6 :                        "Symbol.isConcatSpreadable");
    3594           6 :   CheckWellKnownSymbol(v8::Symbol::GetMatch, "Symbol.match");
    3595           6 :   CheckWellKnownSymbol(v8::Symbol::GetReplace, "Symbol.replace");
    3596           6 :   CheckWellKnownSymbol(v8::Symbol::GetSearch, "Symbol.search");
    3597           6 :   CheckWellKnownSymbol(v8::Symbol::GetSplit, "Symbol.split");
    3598           6 :   CheckWellKnownSymbol(v8::Symbol::GetToPrimitive, "Symbol.toPrimitive");
    3599           6 :   CheckWellKnownSymbol(v8::Symbol::GetToStringTag, "Symbol.toStringTag");
    3600           6 : }
    3601             : 
    3602             : 
    3603       28343 : THREADED_TEST(GlobalPrivates) {
    3604           6 :   i::FLAG_allow_natives_syntax = true;
    3605           6 :   LocalContext env;
    3606           6 :   v8::Isolate* isolate = env->GetIsolate();
    3607          12 :   v8::HandleScope scope(isolate);
    3608             : 
    3609           6 :   v8::Local<String> name = v8_str("my-private");
    3610           6 :   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
    3611           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3612          18 :   CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
    3613             :             .FromJust());
    3614             : 
    3615           6 :   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
    3616          12 :   CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
    3617             : 
    3618           6 :   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
    3619          12 :   CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
    3620             : 
    3621             :   CompileRun("var intern = %CreatePrivateSymbol('my-private')");
    3622             :   v8::Local<Value> intern =
    3623          30 :       env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
    3624          18 :   CHECK(!obj->Has(env.local(), intern).FromJust());
    3625           6 : }
    3626             : 
    3627             : 
    3628             : class ScopedArrayBufferContents {
    3629             :  public:
    3630             :   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
    3631          36 :       : contents_(contents) {}
    3632          36 :   ~ScopedArrayBufferContents() { free(contents_.AllocationBase()); }
    3633             :   void* Data() const { return contents_.Data(); }
    3634             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3635             : 
    3636             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3637             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3638             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3639             :     return contents_.AllocationMode();
    3640             :   }
    3641             : 
    3642             :  private:
    3643             :   const v8::ArrayBuffer::Contents contents_;
    3644             : };
    3645             : 
    3646             : template <typename T>
    3647         282 : static void CheckInternalFieldsAreZero(v8::Local<T> value) {
    3648         282 :   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
    3649         564 :   for (int i = 0; i < value->InternalFieldCount(); i++) {
    3650        1692 :     CHECK_EQ(0, value->GetInternalField(i)
    3651             :                     ->Int32Value(CcTest::isolate()->GetCurrentContext())
    3652             :                     .FromJust());
    3653             :   }
    3654         282 : }
    3655             : 
    3656             : 
    3657       28343 : THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
    3658           6 :   LocalContext env;
    3659           6 :   v8::Isolate* isolate = env->GetIsolate();
    3660          12 :   v8::HandleScope handle_scope(isolate);
    3661             : 
    3662           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
    3663           6 :   CheckInternalFieldsAreZero(ab);
    3664           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3665           6 :   CHECK(!ab->IsExternal());
    3666           6 :   CcTest::CollectAllGarbage();
    3667             : 
    3668          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3669           6 :   CHECK(ab->IsExternal());
    3670             : 
    3671           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3672             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3673           6 :   CHECK_NOT_NULL(data);
    3674          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3675             : 
    3676             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    3677          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3678             : 
    3679             :   result = CompileRun(
    3680             :       "var u8 = new Uint8Array(ab);"
    3681             :       "u8[0] = 0xFF;"
    3682             :       "u8[1] = 0xAA;"
    3683             :       "u8.length");
    3684          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3685          12 :   CHECK_EQ(0xFF, data[0]);
    3686          12 :   CHECK_EQ(0xAA, data[1]);
    3687           6 :   data[0] = 0xCC;
    3688           6 :   data[1] = 0x11;
    3689             :   result = CompileRun("u8[0] + u8[1]");
    3690          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3691           6 : }
    3692             : 
    3693             : 
    3694       28343 : THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
    3695           6 :   LocalContext env;
    3696           6 :   v8::Isolate* isolate = env->GetIsolate();
    3697          12 :   v8::HandleScope handle_scope(isolate);
    3698             : 
    3699             : 
    3700             :   v8::Local<v8::Value> result = CompileRun(
    3701             :       "var ab1 = new ArrayBuffer(2);"
    3702             :       "var u8_a = new Uint8Array(ab1);"
    3703             :       "u8_a[0] = 0xAA;"
    3704             :       "u8_a[1] = 0xFF; u8_a.buffer");
    3705             :   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
    3706           6 :   CheckInternalFieldsAreZero(ab1);
    3707           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    3708           6 :   CHECK(!ab1->IsExternal());
    3709          12 :   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
    3710           6 :   CHECK(ab1->IsExternal());
    3711             : 
    3712             :   result = CompileRun("ab1.byteLength");
    3713          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    3714             :   result = CompileRun("u8_a[0]");
    3715          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    3716             :   result = CompileRun("u8_a[1]");
    3717          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3718             :   result = CompileRun(
    3719             :       "var u8_b = new Uint8Array(ab1);"
    3720             :       "u8_b[0] = 0xBB;"
    3721             :       "u8_a[0]");
    3722          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    3723             :   result = CompileRun("u8_b[1]");
    3724          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3725             : 
    3726           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    3727             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    3728          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    3729          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    3730           6 :   ab1_data[0] = 0xCC;
    3731           6 :   ab1_data[1] = 0x11;
    3732             :   result = CompileRun("u8_a[0] + u8_a[1]");
    3733          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3734           6 : }
    3735             : 
    3736             : 
    3737       28343 : THREADED_TEST(ArrayBuffer_External) {
    3738           6 :   LocalContext env;
    3739           6 :   v8::Isolate* isolate = env->GetIsolate();
    3740          12 :   v8::HandleScope handle_scope(isolate);
    3741             : 
    3742             :   i::ScopedVector<uint8_t> my_data(100);
    3743             :   memset(my_data.start(), 0, 100);
    3744             :   Local<v8::ArrayBuffer> ab3 =
    3745           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3746           6 :   CheckInternalFieldsAreZero(ab3);
    3747           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    3748           6 :   CHECK(ab3->IsExternal());
    3749             : 
    3750          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    3751             : 
    3752             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    3753          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3754             : 
    3755             :   result = CompileRun(
    3756             :       "var u8_b = new Uint8Array(ab3);"
    3757             :       "u8_b[0] = 0xBB;"
    3758             :       "u8_b[1] = 0xCC;"
    3759             :       "u8_b.length");
    3760          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3761          12 :   CHECK_EQ(0xBB, my_data[0]);
    3762          12 :   CHECK_EQ(0xCC, my_data[1]);
    3763           6 :   my_data[0] = 0xCC;
    3764           6 :   my_data[1] = 0x11;
    3765             :   result = CompileRun("u8_b[0] + u8_b[1]");
    3766          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3767           6 : }
    3768             : 
    3769       28343 : THREADED_TEST(ArrayBuffer_DisableDetach) {
    3770           6 :   LocalContext env;
    3771           6 :   v8::Isolate* isolate = env->GetIsolate();
    3772          12 :   v8::HandleScope handle_scope(isolate);
    3773             : 
    3774             :   i::ScopedVector<uint8_t> my_data(100);
    3775             :   memset(my_data.start(), 0, 100);
    3776             :   Local<v8::ArrayBuffer> ab =
    3777           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3778           6 :   CHECK(ab->IsDetachable());
    3779             : 
    3780             :   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
    3781             :   buf->set_is_detachable(false);
    3782             : 
    3783          12 :   CHECK(!ab->IsDetachable());
    3784           6 : }
    3785             : 
    3786          12 : static void CheckDataViewIsDetached(v8::Local<v8::DataView> dv) {
    3787          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
    3788          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
    3789          12 : }
    3790             : 
    3791         108 : static void CheckIsDetached(v8::Local<v8::TypedArray> ta) {
    3792         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
    3793         108 :   CHECK_EQ(0, static_cast<int>(ta->Length()));
    3794         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
    3795         108 : }
    3796             : 
    3797          54 : static void CheckIsTypedArrayVarDetached(const char* name) {
    3798             :   i::ScopedVector<char> source(1024);
    3799             :   i::SNPrintF(source,
    3800             :               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
    3801          54 :               name, name, name);
    3802          54 :   CHECK(CompileRun(source.start())->IsTrue());
    3803             :   v8::Local<v8::TypedArray> ta =
    3804          54 :       v8::Local<v8::TypedArray>::Cast(CompileRun(name));
    3805          54 :   CheckIsDetached(ta);
    3806          54 : }
    3807             : 
    3808             : template <typename TypedArray, int kElementSize>
    3809          54 : static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
    3810             :                                         int byteOffset, int length) {
    3811          54 :   v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
    3812          54 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
    3813          54 :   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
    3814          54 :   CHECK_EQ(length, static_cast<int>(ta->Length()));
    3815          54 :   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
    3816          54 :   return ta;
    3817             : }
    3818             : 
    3819       28343 : THREADED_TEST(ArrayBuffer_DetachingApi) {
    3820           6 :   LocalContext env;
    3821           6 :   v8::Isolate* isolate = env->GetIsolate();
    3822          12 :   v8::HandleScope handle_scope(isolate);
    3823             : 
    3824           6 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
    3825             : 
    3826             :   v8::Local<v8::Uint8Array> u8a =
    3827           6 :       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
    3828             :   v8::Local<v8::Uint8ClampedArray> u8c =
    3829           6 :       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
    3830             :   v8::Local<v8::Int8Array> i8a =
    3831           6 :       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
    3832             : 
    3833             :   v8::Local<v8::Uint16Array> u16a =
    3834           6 :       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
    3835             :   v8::Local<v8::Int16Array> i16a =
    3836           6 :       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
    3837             : 
    3838             :   v8::Local<v8::Uint32Array> u32a =
    3839           6 :       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
    3840             :   v8::Local<v8::Int32Array> i32a =
    3841           6 :       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
    3842             : 
    3843             :   v8::Local<v8::Float32Array> f32a =
    3844           6 :       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
    3845             :   v8::Local<v8::Float64Array> f64a =
    3846           6 :       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
    3847             : 
    3848           6 :   v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
    3849           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
    3850           6 :   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
    3851           6 :   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
    3852             : 
    3853          12 :   ScopedArrayBufferContents contents(buffer->Externalize());
    3854           6 :   buffer->Detach();
    3855           6 :   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
    3856           6 :   CheckIsDetached(u8a);
    3857           6 :   CheckIsDetached(u8c);
    3858           6 :   CheckIsDetached(i8a);
    3859           6 :   CheckIsDetached(u16a);
    3860           6 :   CheckIsDetached(i16a);
    3861           6 :   CheckIsDetached(u32a);
    3862           6 :   CheckIsDetached(i32a);
    3863           6 :   CheckIsDetached(f32a);
    3864           6 :   CheckIsDetached(f64a);
    3865          12 :   CheckDataViewIsDetached(dv);
    3866           6 : }
    3867             : 
    3868       28343 : THREADED_TEST(ArrayBuffer_DetachingScript) {
    3869           6 :   LocalContext env;
    3870           6 :   v8::Isolate* isolate = env->GetIsolate();
    3871          12 :   v8::HandleScope handle_scope(isolate);
    3872             : 
    3873             :   CompileRun(
    3874             :       "var ab = new ArrayBuffer(1024);"
    3875             :       "var u8a = new Uint8Array(ab, 1, 1023);"
    3876             :       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
    3877             :       "var i8a = new Int8Array(ab, 1, 1023);"
    3878             :       "var u16a = new Uint16Array(ab, 2, 511);"
    3879             :       "var i16a = new Int16Array(ab, 2, 511);"
    3880             :       "var u32a = new Uint32Array(ab, 4, 255);"
    3881             :       "var i32a = new Int32Array(ab, 4, 255);"
    3882             :       "var f32a = new Float32Array(ab, 4, 255);"
    3883             :       "var f64a = new Float64Array(ab, 8, 127);"
    3884             :       "var dv = new DataView(ab, 1, 1023);");
    3885             : 
    3886             :   v8::Local<v8::ArrayBuffer> ab =
    3887             :       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
    3888             : 
    3889           6 :   v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
    3890             : 
    3891          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3892           6 :   ab->Detach();
    3893           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3894           6 :   CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
    3895             : 
    3896           6 :   CheckIsTypedArrayVarDetached("u8a");
    3897           6 :   CheckIsTypedArrayVarDetached("u8c");
    3898           6 :   CheckIsTypedArrayVarDetached("i8a");
    3899           6 :   CheckIsTypedArrayVarDetached("u16a");
    3900           6 :   CheckIsTypedArrayVarDetached("i16a");
    3901           6 :   CheckIsTypedArrayVarDetached("u32a");
    3902           6 :   CheckIsTypedArrayVarDetached("i32a");
    3903           6 :   CheckIsTypedArrayVarDetached("f32a");
    3904           6 :   CheckIsTypedArrayVarDetached("f64a");
    3905             : 
    3906           6 :   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
    3907          12 :   CheckDataViewIsDetached(dv);
    3908           6 : }
    3909             : 
    3910       28343 : THREADED_TEST(ArrayBuffer_AllocationInformation) {
    3911           6 :   LocalContext env;
    3912           6 :   v8::Isolate* isolate = env->GetIsolate();
    3913          12 :   v8::HandleScope handle_scope(isolate);
    3914             : 
    3915             :   const size_t ab_size = 1024;
    3916           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, ab_size);
    3917          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3918             : 
    3919             :   // Array buffers should have normal allocation mode.
    3920           6 :   CHECK_EQ(contents.AllocationMode(),
    3921             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
    3922             :   // The allocation must contain the buffer (normally they will be equal, but
    3923             :   // this is not required by the contract).
    3924           6 :   CHECK_NOT_NULL(contents.AllocationBase());
    3925             :   const uintptr_t alloc =
    3926           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
    3927           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
    3928           6 :   CHECK_LE(alloc, data);
    3929          12 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
    3930           6 : }
    3931             : 
    3932       28343 : THREADED_TEST(ArrayBuffer_ExternalizeEmpty) {
    3933           6 :   LocalContext env;
    3934           6 :   v8::Isolate* isolate = env->GetIsolate();
    3935          12 :   v8::HandleScope handle_scope(isolate);
    3936             : 
    3937           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 0);
    3938           6 :   CheckInternalFieldsAreZero(ab);
    3939           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3940           6 :   CHECK(!ab->IsExternal());
    3941             : 
    3942             :   // Externalize the buffer (taking ownership of the backing store memory).
    3943          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3944             : 
    3945           6 :   Local<v8::Uint8Array> u8a = v8::Uint8Array::New(ab, 0, 0);
    3946             :   // Calling Buffer() will materialize the ArrayBuffer (transitioning it from
    3947             :   // on-heap to off-heap if need be). This should not affect whether it is
    3948             :   // marked as is_external or not.
    3949           6 :   USE(u8a->Buffer());
    3950             : 
    3951          12 :   CHECK(ab->IsExternal());
    3952           6 : }
    3953             : 
    3954             : class ScopedSharedArrayBufferContents {
    3955             :  public:
    3956             :   explicit ScopedSharedArrayBufferContents(
    3957             :       const v8::SharedArrayBuffer::Contents& contents)
    3958          18 :       : contents_(contents) {}
    3959          18 :   ~ScopedSharedArrayBufferContents() { free(contents_.AllocationBase()); }
    3960             :   void* Data() const { return contents_.Data(); }
    3961             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3962             : 
    3963             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3964             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3965             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3966             :     return contents_.AllocationMode();
    3967             :   }
    3968             : 
    3969             :  private:
    3970             :   const v8::SharedArrayBuffer::Contents contents_;
    3971             : };
    3972             : 
    3973             : 
    3974       28343 : THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
    3975           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    3976           6 :   LocalContext env;
    3977           6 :   v8::Isolate* isolate = env->GetIsolate();
    3978          12 :   v8::HandleScope handle_scope(isolate);
    3979             : 
    3980           6 :   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
    3981           6 :   CheckInternalFieldsAreZero(ab);
    3982           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3983           6 :   CHECK(!ab->IsExternal());
    3984           6 :   CcTest::CollectAllGarbage();
    3985             : 
    3986          12 :   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
    3987           6 :   CHECK(ab->IsExternal());
    3988             : 
    3989           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3990             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3991           6 :   CHECK_NOT_NULL(data);
    3992          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3993             : 
    3994             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    3995          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3996             : 
    3997             :   result = CompileRun(
    3998             :       "var u8 = new Uint8Array(ab);"
    3999             :       "u8[0] = 0xFF;"
    4000             :       "u8[1] = 0xAA;"
    4001             :       "u8.length");
    4002          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    4003          12 :   CHECK_EQ(0xFF, data[0]);
    4004          12 :   CHECK_EQ(0xAA, data[1]);
    4005           6 :   data[0] = 0xCC;
    4006           6 :   data[1] = 0x11;
    4007             :   result = CompileRun("u8[0] + u8[1]");
    4008          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4009           6 : }
    4010             : 
    4011             : 
    4012       28343 : THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
    4013           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4014           6 :   LocalContext env;
    4015           6 :   v8::Isolate* isolate = env->GetIsolate();
    4016          12 :   v8::HandleScope handle_scope(isolate);
    4017             : 
    4018             : 
    4019             :   v8::Local<v8::Value> result = CompileRun(
    4020             :       "var ab1 = new SharedArrayBuffer(2);"
    4021             :       "var u8_a = new Uint8Array(ab1);"
    4022             :       "u8_a[0] = 0xAA;"
    4023             :       "u8_a[1] = 0xFF; u8_a.buffer");
    4024             :   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
    4025           6 :   CheckInternalFieldsAreZero(ab1);
    4026           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    4027           6 :   CHECK(!ab1->IsExternal());
    4028          12 :   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
    4029           6 :   CHECK(ab1->IsExternal());
    4030             : 
    4031             :   result = CompileRun("ab1.byteLength");
    4032          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    4033             :   result = CompileRun("u8_a[0]");
    4034          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    4035             :   result = CompileRun("u8_a[1]");
    4036          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    4037             :   result = CompileRun(
    4038             :       "var u8_b = new Uint8Array(ab1);"
    4039             :       "u8_b[0] = 0xBB;"
    4040             :       "u8_a[0]");
    4041          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    4042             :   result = CompileRun("u8_b[1]");
    4043          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    4044             : 
    4045           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    4046             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    4047          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    4048          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    4049           6 :   ab1_data[0] = 0xCC;
    4050           6 :   ab1_data[1] = 0x11;
    4051             :   result = CompileRun("u8_a[0] + u8_a[1]");
    4052          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4053           6 : }
    4054             : 
    4055             : 
    4056       28343 : THREADED_TEST(SharedArrayBuffer_External) {
    4057           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4058           6 :   LocalContext env;
    4059           6 :   v8::Isolate* isolate = env->GetIsolate();
    4060          12 :   v8::HandleScope handle_scope(isolate);
    4061             : 
    4062             :   i::ScopedVector<uint8_t> my_data(100);
    4063             :   memset(my_data.start(), 0, 100);
    4064             :   Local<v8::SharedArrayBuffer> ab3 =
    4065           6 :       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
    4066           6 :   CheckInternalFieldsAreZero(ab3);
    4067           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    4068           6 :   CHECK(ab3->IsExternal());
    4069             : 
    4070          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    4071             : 
    4072             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    4073          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    4074             : 
    4075             :   result = CompileRun(
    4076             :       "var u8_b = new Uint8Array(ab3);"
    4077             :       "u8_b[0] = 0xBB;"
    4078             :       "u8_b[1] = 0xCC;"
    4079             :       "u8_b.length");
    4080          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    4081          12 :   CHECK_EQ(0xBB, my_data[0]);
    4082          12 :   CHECK_EQ(0xCC, my_data[1]);
    4083           6 :   my_data[0] = 0xCC;
    4084           6 :   my_data[1] = 0x11;
    4085             :   result = CompileRun("u8_b[0] + u8_b[1]");
    4086          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4087           6 : }
    4088             : 
    4089             : 
    4090       28343 : THREADED_TEST(HiddenProperties) {
    4091           6 :   LocalContext env;
    4092           6 :   v8::Isolate* isolate = env->GetIsolate();
    4093          12 :   v8::HandleScope scope(isolate);
    4094             : 
    4095           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4096             :   v8::Local<v8::Private> key =
    4097           6 :       v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
    4098           6 :   v8::Local<v8::String> empty = v8_str("");
    4099           6 :   v8::Local<v8::String> prop_name = v8_str("prop_name");
    4100             : 
    4101           6 :   CcTest::CollectAllGarbage();
    4102             : 
    4103             :   // Make sure delete of a non-existent hidden value works
    4104          12 :   obj->DeletePrivate(env.local(), key).FromJust();
    4105             : 
    4106          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
    4107             :             .FromJust());
    4108          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
    4109             :                      .ToLocalChecked()
    4110             :                      ->Int32Value(env.local())
    4111             :                      .FromJust());
    4112          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4113             :             .FromJust());
    4114          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4115             :                      .ToLocalChecked()
    4116             :                      ->Int32Value(env.local())
    4117             :                      .FromJust());
    4118             : 
    4119           6 :   CcTest::CollectAllGarbage();
    4120             : 
    4121             :   // Make sure we do not find the hidden property.
    4122          12 :   CHECK(!obj->Has(env.local(), empty).FromJust());
    4123          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4124             :                      .ToLocalChecked()
    4125             :                      ->Int32Value(env.local())
    4126             :                      .FromJust());
    4127          12 :   CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
    4128          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4129             :                      .ToLocalChecked()
    4130             :                      ->Int32Value(env.local())
    4131             :                      .FromJust());
    4132          18 :   CHECK(
    4133             :       obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
    4134          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4135             :                      .ToLocalChecked()
    4136             :                      ->Int32Value(env.local())
    4137             :                      .FromJust());
    4138          24 :   CHECK_EQ(2003, obj->Get(env.local(), empty)
    4139             :                      .ToLocalChecked()
    4140             :                      ->Int32Value(env.local())
    4141             :                      .FromJust());
    4142             : 
    4143           6 :   CcTest::CollectAllGarbage();
    4144             : 
    4145             :   // Add another property and delete it afterwards to force the object in
    4146             :   // slow case.
    4147          18 :   CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
    4148             :             .FromJust());
    4149          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4150             :                      .ToLocalChecked()
    4151             :                      ->Int32Value(env.local())
    4152             :                      .FromJust());
    4153          24 :   CHECK_EQ(2008, obj->Get(env.local(), prop_name)
    4154             :                      .ToLocalChecked()
    4155             :                      ->Int32Value(env.local())
    4156             :                      .FromJust());
    4157          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4158             :                      .ToLocalChecked()
    4159             :                      ->Int32Value(env.local())
    4160             :                      .FromJust());
    4161          12 :   CHECK(obj->Delete(env.local(), prop_name).FromJust());
    4162          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4163             :                      .ToLocalChecked()
    4164             :                      ->Int32Value(env.local())
    4165             :                      .FromJust());
    4166             : 
    4167           6 :   CcTest::CollectAllGarbage();
    4168             : 
    4169          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4170             :             .FromJust());
    4171          12 :   CHECK(obj->DeletePrivate(env.local(), key).FromJust());
    4172          18 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4173           6 : }
    4174             : 
    4175             : 
    4176       28343 : THREADED_TEST(Regress97784) {
    4177             :   // Regression test for crbug.com/97784
    4178             :   // Messing with the Object.prototype should not have effect on
    4179             :   // hidden properties.
    4180           6 :   LocalContext env;
    4181          12 :   v8::HandleScope scope(env->GetIsolate());
    4182             : 
    4183           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4184             :   v8::Local<v8::Private> key =
    4185          12 :       v8::Private::New(env->GetIsolate(), v8_str("hidden"));
    4186             : 
    4187             :   CompileRun(
    4188             :       "set_called = false;"
    4189             :       "Object.defineProperty("
    4190             :       "    Object.prototype,"
    4191             :       "    'hidden',"
    4192             :       "    {get: function() { return 45; },"
    4193             :       "     set: function() { set_called = true; }})");
    4194             : 
    4195          12 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4196             :   // Make sure that the getter and setter from Object.prototype is not invoked.
    4197             :   // If it did we would have full access to the hidden properties in
    4198             :   // the accessor.
    4199          18 :   CHECK(
    4200             :       obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
    4201             :           .FromJust());
    4202             :   ExpectFalse("set_called");
    4203          18 :   CHECK_EQ(42, obj->GetPrivate(env.local(), key)
    4204             :                    .ToLocalChecked()
    4205             :                    ->Int32Value(env.local())
    4206           6 :                    .FromJust());
    4207           6 : }
    4208             : 
    4209             : 
    4210       28343 : THREADED_TEST(External) {
    4211           6 :   v8::HandleScope scope(CcTest::isolate());
    4212           6 :   int x = 3;
    4213           6 :   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
    4214          12 :   LocalContext env;
    4215          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
    4216             :   Local<Value> reext_obj = CompileRun("this.ext");
    4217             :   v8::Local<v8::External> reext = reext_obj.As<v8::External>();
    4218           6 :   int* ptr = static_cast<int*>(reext->Value());
    4219           6 :   CHECK_EQ(3, x);
    4220           6 :   *ptr = 10;
    4221           6 :   CHECK_EQ(x, 10);
    4222             : 
    4223             :   {
    4224             :     i::Handle<i::Object> obj = v8::Utils::OpenHandle(*ext);
    4225          18 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4226           6 :     CHECK(ext->IsExternal());
    4227           6 :     CHECK(!CompileRun("new Set().add(this.ext)").IsEmpty());
    4228          18 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4229           6 :     CHECK(ext->IsExternal());
    4230             :   }
    4231             : 
    4232             :   // Make sure unaligned pointers are wrapped properly.
    4233           6 :   char* data = i::StrDup("0123456789");
    4234           6 :   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
    4235           6 :   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
    4236           6 :   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
    4237           6 :   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
    4238             : 
    4239           6 :   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
    4240           6 :   CHECK_EQ('0', *char_ptr);
    4241           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
    4242           6 :   CHECK_EQ('1', *char_ptr);
    4243           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
    4244           6 :   CHECK_EQ('2', *char_ptr);
    4245           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
    4246           6 :   CHECK_EQ('3', *char_ptr);
    4247           6 :   i::DeleteArray(data);
    4248           6 : }
    4249             : 
    4250             : 
    4251       28343 : THREADED_TEST(GlobalHandle) {
    4252           6 :   v8::Isolate* isolate = CcTest::isolate();
    4253             :   v8::Persistent<String> global;
    4254             :   {
    4255           6 :     v8::HandleScope scope(isolate);
    4256          12 :     global.Reset(isolate, v8_str("str"));
    4257             :   }
    4258             :   {
    4259           6 :     v8::HandleScope scope(isolate);
    4260           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4261             :   }
    4262             :   global.Reset();
    4263             :   {
    4264           6 :     v8::HandleScope scope(isolate);
    4265          12 :     global.Reset(isolate, v8_str("str"));
    4266             :   }
    4267             :   {
    4268           6 :     v8::HandleScope scope(isolate);
    4269           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4270             :   }
    4271             :   global.Reset();
    4272           6 : }
    4273             : 
    4274             : 
    4275       28343 : THREADED_TEST(ResettingGlobalHandle) {
    4276          12 :   v8::Isolate* isolate = CcTest::isolate();
    4277             :   v8::Persistent<String> global;
    4278             :   {
    4279           6 :     v8::HandleScope scope(isolate);
    4280          12 :     global.Reset(isolate, v8_str("str"));
    4281             :   }
    4282          18 :   v8::internal::GlobalHandles* global_handles =
    4283             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4284             :   int initial_handle_count = global_handles->global_handles_count();
    4285             :   {
    4286           6 :     v8::HandleScope scope(isolate);
    4287           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4288             :   }
    4289             :   {
    4290           6 :     v8::HandleScope scope(isolate);
    4291          12 :     global.Reset(isolate, v8_str("longer"));
    4292             :   }
    4293           6 :   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
    4294             :   {
    4295           6 :     v8::HandleScope scope(isolate);
    4296           6 :     CHECK_EQ(6, v8::Local<String>::New(isolate, global)->Length());
    4297             :   }
    4298             :   global.Reset();
    4299          12 :   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
    4300           6 : }
    4301             : 
    4302             : 
    4303       28343 : THREADED_TEST(ResettingGlobalHandleToEmpty) {
    4304          12 :   v8::Isolate* isolate = CcTest::isolate();
    4305             :   v8::Persistent<String> global;
    4306             :   {
    4307           6 :     v8::HandleScope scope(isolate);
    4308          12 :     global.Reset(isolate, v8_str("str"));
    4309             :   }
    4310          12 :   v8::internal::GlobalHandles* global_handles =
    4311             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4312             :   int initial_handle_count = global_handles->global_handles_count();
    4313             :   {
    4314           6 :     v8::HandleScope scope(isolate);
    4315           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4316             :   }
    4317             :   {
    4318           6 :     v8::HandleScope scope(isolate);
    4319             :     Local<String> empty;
    4320           6 :     global.Reset(isolate, empty);
    4321             :   }
    4322           6 :   CHECK(global.IsEmpty());
    4323          12 :   CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
    4324           6 : }
    4325             : 
    4326             : 
    4327             : template <class T>
    4328             : static v8::Global<T> PassUnique(v8::Global<T> unique) {
    4329             :   return unique.Pass();
    4330             : }
    4331             : 
    4332             : 
    4333             : template <class T>
    4334             : static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
    4335             :                                   const v8::Persistent<T>& global) {
    4336             :   v8::Global<String> unique(isolate, global);
    4337             :   return unique.Pass();
    4338             : }
    4339             : 
    4340             : 
    4341       28343 : THREADED_TEST(Global) {
    4342          12 :   v8::Isolate* isolate = CcTest::isolate();
    4343             :   v8::Persistent<String> global;
    4344             :   {
    4345           6 :     v8::HandleScope scope(isolate);
    4346          12 :     global.Reset(isolate, v8_str("str"));
    4347             :   }
    4348          42 :   v8::internal::GlobalHandles* global_handles =
    4349             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4350             :   int initial_handle_count = global_handles->global_handles_count();
    4351             :   {
    4352             :     v8::Global<String> unique(isolate, global);
    4353           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4354             :     // Test assignment via Pass
    4355             :     {
    4356             :       v8::Global<String> copy = unique.Pass();
    4357           6 :       CHECK(unique.IsEmpty());
    4358           6 :       CHECK(copy == global);
    4359           6 :       CHECK_EQ(initial_handle_count + 1,
    4360             :                global_handles->global_handles_count());
    4361             :       unique = copy.Pass();
    4362             :     }
    4363             :     // Test ctor via Pass
    4364             :     {
    4365             :       v8::Global<String> copy(unique.Pass());
    4366           6 :       CHECK(unique.IsEmpty());
    4367           6 :       CHECK(copy == global);
    4368           6 :       CHECK_EQ(initial_handle_count + 1,
    4369             :                global_handles->global_handles_count());
    4370             :       unique = copy.Pass();
    4371             :     }
    4372             :     // Test pass through function call
    4373             :     {
    4374             :       v8::Global<String> copy = PassUnique(unique.Pass());
    4375           6 :       CHECK(unique.IsEmpty());
    4376           6 :       CHECK(copy == global);
    4377           6 :       CHECK_EQ(initial_handle_count + 1,
    4378             :                global_handles->global_handles_count());
    4379             :       unique = copy.Pass();
    4380             :     }
    4381           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4382             :   }
    4383             :   // Test pass from function call
    4384             :   {
    4385             :     v8::Global<String> unique = ReturnUnique(isolate, global);
    4386           6 :     CHECK(unique == global);
    4387           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4388             :   }
    4389           6 :   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
    4390             :   global.Reset();
    4391           6 : }
    4392             : 
    4393             : 
    4394             : namespace {
    4395             : 
    4396             : class TwoPassCallbackData;
    4397             : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4398             : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4399             : 
    4400             : 
    4401             : class TwoPassCallbackData {
    4402             :  public:
    4403         215 :   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
    4404             :       : first_pass_called_(false),
    4405             :         second_pass_called_(false),
    4406             :         trigger_gc_(false),
    4407         430 :         instance_counter_(instance_counter) {
    4408         215 :     HandleScope scope(isolate);
    4409             :     i::ScopedVector<char> buffer(40);
    4410         215 :     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
    4411             :     auto string =
    4412             :         v8::String::NewFromUtf8(isolate, buffer.start(),
    4413         215 :                                 v8::NewStringType::kNormal).ToLocalChecked();
    4414             :     cell_.Reset(isolate, string);
    4415         430 :     (*instance_counter_)++;
    4416         215 :   }
    4417             : 
    4418         215 :   ~TwoPassCallbackData() {
    4419         215 :     CHECK(first_pass_called_);
    4420         215 :     CHECK(second_pass_called_);
    4421         215 :     CHECK(cell_.IsEmpty());
    4422         215 :     (*instance_counter_)--;
    4423         215 :   }
    4424             : 
    4425         215 :   void FirstPass() {
    4426         215 :     CHECK(!first_pass_called_);
    4427         215 :     CHECK(!second_pass_called_);
    4428         215 :     CHECK(!cell_.IsEmpty());
    4429             :     cell_.Reset();
    4430         215 :     first_pass_called_ = true;
    4431         215 :   }
    4432             : 
    4433         215 :   void SecondPass() {
    4434         215 :     CHECK(first_pass_called_);
    4435         215 :     CHECK(!second_pass_called_);
    4436         215 :     CHECK(cell_.IsEmpty());
    4437         215 :     second_pass_called_ = true;
    4438         215 :     delete this;
    4439         215 :   }
    4440             : 
    4441             :   void SetWeak() {
    4442             :     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
    4443             :   }
    4444             : 
    4445          15 :   void MarkTriggerGc() { trigger_gc_ = true; }
    4446             :   bool trigger_gc() { return trigger_gc_; }
    4447             : 
    4448             :   int* instance_counter() { return instance_counter_; }
    4449             : 
    4450             :  private:
    4451             :   bool first_pass_called_;
    4452             :   bool second_pass_called_;
    4453             :   bool trigger_gc_;
    4454             :   v8::Global<v8::String> cell_;
    4455             :   int* instance_counter_;
    4456             : };
    4457             : 
    4458             : 
    4459         445 : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4460         215 :   ApiTestFuzzer::Fuzz();
    4461         215 :   bool trigger_gc = data.GetParameter()->trigger_gc();
    4462         215 :   int* instance_counter = data.GetParameter()->instance_counter();
    4463         215 :   data.GetParameter()->SecondPass();
    4464         430 :   if (!trigger_gc) return;
    4465          15 :   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
    4466             :   data_2->SetWeak();
    4467          15 :   CcTest::CollectAllGarbage();
    4468             : }
    4469             : 
    4470             : 
    4471         430 : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4472         215 :   data.GetParameter()->FirstPass();
    4473             :   data.SetSecondPassCallback(SecondPassCallback);
    4474         215 : }
    4475             : 
    4476             : }  // namespace
    4477             : 
    4478             : 
    4479       28342 : TEST(TwoPassPhantomCallbacks) {
    4480           5 :   auto isolate = CcTest::isolate();
    4481             :   const size_t kLength = 20;
    4482           5 :   int instance_counter = 0;
    4483         105 :   for (size_t i = 0; i < kLength; ++i) {
    4484         100 :     auto data = new TwoPassCallbackData(isolate, &instance_counter);
    4485             :     data->SetWeak();
    4486             :   }
    4487           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4488           5 :   CcTest::CollectAllGarbage();
    4489           5 :   EmptyMessageQueues(isolate);
    4490           5 :   CHECK_EQ(0, instance_counter);
    4491           5 : }
    4492             : 
    4493             : 
    4494       28342 : TEST(TwoPassPhantomCallbacksNestedGc) {
    4495           5 :   auto isolate = CcTest::isolate();
    4496             :   const size_t kLength = 20;
    4497             :   TwoPassCallbackData* array[kLength];
    4498           5 :   int instance_counter = 0;
    4499         105 :   for (size_t i = 0; i < kLength; ++i) {
    4500         100 :     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
    4501             :     array[i]->SetWeak();
    4502             :   }
    4503           5 :   array[5]->MarkTriggerGc();
    4504           5 :   array[10]->MarkTriggerGc();
    4505           5 :   array[15]->MarkTriggerGc();
    4506           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4507           5 :   CcTest::CollectAllGarbage();
    4508           5 :   EmptyMessageQueues(isolate);
    4509           5 :   CHECK_EQ(0, instance_counter);
    4510           5 : }
    4511             : 
    4512             : 
    4513             : namespace {
    4514             : 
    4515          30 : void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
    4516             : 
    4517             : 
    4518          20 : Local<v8::Object> NewObjectForIntKey(
    4519             :     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
    4520             :     int key) {
    4521             :   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
    4522          20 :   auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
    4523          20 :   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
    4524          20 :   return obj;
    4525             : }
    4526             : 
    4527             : 
    4528             : template <typename K, typename V>
    4529             : class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
    4530             :  public:
    4531             :   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
    4532             :   static const v8::PersistentContainerCallbackType kCallbackType =
    4533             :       v8::kWeakWithInternalFields;
    4534             :   struct WeakCallbackDataType {
    4535             :     MapType* map;
    4536             :     K key;
    4537             :   };
    4538             :   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
    4539             :                                                      Local<V> value) {
    4540          25 :     WeakCallbackDataType* data = new WeakCallbackDataType;
    4541          25 :     data->map = map;
    4542          25 :     data->key = key;
    4543             :     return data;
    4544             :   }
    4545             :   static MapType* MapFromWeakCallbackInfo(
    4546           5 :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4547           5 :     return data.GetParameter()->map;
    4548             :   }
    4549             :   static K KeyFromWeakCallbackInfo(
    4550           5 :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4551          10 :     return data.GetParameter()->key;
    4552             :   }
    4553          25 :   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
    4554           5 :   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
    4555           5 :     CHECK_EQ(IntKeyToVoidPointer(key),
    4556             :              v8::Object::GetAlignedPointerFromInternalField(value, 0));
    4557           5 :   }
    4558             :   static void OnWeakCallback(
    4559             :       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
    4560           5 :   static void DisposeWeak(
    4561             :       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
    4562             :     K key = KeyFromWeakCallbackInfo(info);
    4563           5 :     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
    4564             :     DisposeCallbackData(info.GetParameter());
    4565           5 :   }
    4566             : };
    4567             : 
    4568             : 
    4569             : template <typename Map>
    4570          10 : void TestGlobalValueMap() {
    4571          10 :   LocalContext env;
    4572          20 :   v8::Isolate* isolate = env->GetIsolate();
    4573             :   v8::Global<ObjectTemplate> templ;
    4574             :   {
    4575          10 :     HandleScope scope(isolate);
    4576          10 :     auto t = ObjectTemplate::New(isolate);
    4577          10 :     t->SetInternalFieldCount(1);
    4578          10 :     templ.Reset(isolate, t);
    4579             :   }
    4580             :   Map map(isolate);
    4581          40 :   v8::internal::GlobalHandles* global_handles =
    4582             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4583             :   int initial_handle_count = global_handles->global_handles_count();
    4584          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4585             :   {
    4586          10 :     HandleScope scope(isolate);
    4587          10 :     Local<v8::Object> obj = map.Get(7);
    4588          10 :     CHECK(obj.IsEmpty());
    4589          10 :     Local<v8::Object> expected = v8::Object::New(isolate);
    4590          20 :     map.Set(7, expected);
    4591          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4592          10 :     obj = map.Get(7);
    4593          20 :     CHECK(expected->Equals(env.local(), obj).FromJust());
    4594             :     {
    4595          10 :       typename Map::PersistentValueReference ref = map.GetReference(7);
    4596          20 :       CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4597             :     }
    4598           5 :     v8::Global<v8::Object> removed = map.Remove(7);
    4599          10 :     CHECK_EQ(0, static_cast<int>(map.Size()));
    4600          10 :     CHECK(expected == removed);
    4601          10 :     removed = map.Remove(7);
    4602          10 :     CHECK(removed.IsEmpty());
    4603          20 :     map.Set(8, expected);
    4604          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4605          20 :     map.Set(8, expected);
    4606          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4607             :     {
    4608             :       typename Map::PersistentValueReference ref;
    4609          10 :       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
    4610          30 :       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
    4611          10 :       CHECK_EQ(1, static_cast<int>(map.Size()));
    4612          10 :       CHECK(expected == removed);
    4613          20 :       CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4614          10 :     }
    4615             :   }
    4616          10 :   CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
    4617             :   if (map.IsWeak()) {
    4618           5 :     CcTest::PreciseCollectAllGarbage();
    4619             :   } else {
    4620           5 :     map.Clear();
    4621             :   }
    4622          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4623          10 :   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
    4624             :   {
    4625          10 :     HandleScope scope(isolate);
    4626          10 :     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
    4627          20 :     map.Set(9, value);
    4628          10 :     map.Clear();
    4629             :   }
    4630          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4631          20 :   CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
    4632          10 : }
    4633             : 
    4634             : }  // namespace
    4635             : 
    4636             : 
    4637       28342 : TEST(GlobalValueMap) {
    4638             :   // Default case, w/o weak callbacks:
    4639           5 :   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
    4640             : 
    4641             :   // Custom traits with weak callbacks:
    4642             :   typedef v8::GlobalValueMap<int, v8::Object,
    4643             :                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
    4644           5 :   TestGlobalValueMap<WeakMap>();
    4645           5 : }
    4646             : 
    4647             : 
    4648       28342 : TEST(PersistentValueVector) {
    4649           5 :   LocalContext env;
    4650           5 :   v8::Isolate* isolate = env->GetIsolate();
    4651          15 :   v8::internal::GlobalHandles* global_handles =
    4652             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4653             :   int handle_count = global_handles->global_handles_count();
    4654          10 :   HandleScope scope(isolate);
    4655             : 
    4656           5 :   v8::PersistentValueVector<v8::Object> vector(isolate);
    4657             : 
    4658           5 :   Local<v8::Object> obj1 = v8::Object::New(isolate);
    4659           5 :   Local<v8::Object> obj2 = v8::Object::New(isolate);
    4660           5 :   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
    4661             : 
    4662           5 :   CHECK(vector.IsEmpty());
    4663           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4664             : 
    4665             :   vector.ReserveCapacity(3);
    4666           5 :   CHECK(vector.IsEmpty());
    4667             : 
    4668           5 :   vector.Append(obj1);
    4669           5 :   vector.Append(obj2);
    4670           5 :   vector.Append(obj1);
    4671             :   vector.Append(obj3.Pass());
    4672           5 :   vector.Append(obj1);
    4673             : 
    4674           5 :   CHECK(!vector.IsEmpty());
    4675           5 :   CHECK_EQ(5, static_cast<int>(vector.Size()));
    4676           5 :   CHECK(obj3.IsEmpty());
    4677          15 :   CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
    4678          15 :   CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
    4679          15 :   CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
    4680          20 :   CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
    4681             : 
    4682           5 :   CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
    4683             : 
    4684           5 :   vector.Clear();
    4685           5 :   CHECK(vector.IsEmpty());
    4686           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4687          10 :   CHECK_EQ(handle_count, global_handles->global_handles_count());
    4688           5 : }
    4689             : 
    4690             : 
    4691       28343 : THREADED_TEST(GlobalHandleUpcast) {
    4692           6 :   v8::Isolate* isolate = CcTest::isolate();
    4693           6 :   v8::HandleScope scope(isolate);
    4694           6 :   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
    4695             :   v8::Persistent<String> global_string(isolate, local);
    4696             :   v8::Persistent<Value>& global_value =
    4697             :       v8::Persistent<Value>::Cast(global_string);
    4698           6 :   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
    4699           6 :   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
    4700           6 :   global_string.Reset();
    4701           6 : }
    4702             : 
    4703             : 
    4704       28343 : THREADED_TEST(HandleEquality) {
    4705           6 :   v8::Isolate* isolate = CcTest::isolate();
    4706             :   v8::Persistent<String> global1;
    4707             :   v8::Persistent<String> global2;
    4708             :   {
    4709           6 :     v8::HandleScope scope(isolate);
    4710          12 :     global1.Reset(isolate, v8_str("str"));
    4711          12 :     global2.Reset(isolate, v8_str("str2"));
    4712             :   }
    4713           6 :   CHECK(global1 == global1);
    4714           6 :   CHECK(!(global1 != global1));
    4715             :   {
    4716           6 :     v8::HandleScope scope(isolate);
    4717             :     Local<String> local1 = Local<String>::New(isolate, global1);
    4718             :     Local<String> local2 = Local<String>::New(isolate, global2);
    4719             : 
    4720           6 :     CHECK(global1 == local1);
    4721           6 :     CHECK(!(global1 != local1));
    4722           6 :     CHECK(local1 == global1);
    4723           6 :     CHECK(!(local1 != global1));
    4724             : 
    4725           6 :     CHECK(!(global1 == local2));
    4726           6 :     CHECK(global1 != local2);
    4727           6 :     CHECK(!(local2 == global1));
    4728           6 :     CHECK(local2 != global1);
    4729             : 
    4730           6 :     CHECK(!(local1 == local2));
    4731           6 :     CHECK(local1 != local2);
    4732             : 
    4733             :     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
    4734           6 :     CHECK(local1 == anotherLocal1);
    4735           6 :     CHECK(!(local1 != anotherLocal1));
    4736             :   }
    4737             :   global1.Reset();
    4738             :   global2.Reset();
    4739           6 : }
    4740             : 
    4741             : 
    4742       28343 : THREADED_TEST(LocalHandle) {
    4743           6 :   v8::HandleScope scope(CcTest::isolate());
    4744             :   v8::Local<String> local =
    4745           6 :       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
    4746           6 :   CHECK_EQ(3, local->Length());
    4747           6 : }
    4748             : 
    4749             : 
    4750             : class WeakCallCounter {
    4751             :  public:
    4752           5 :   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
    4753             :   int id() { return id_; }
    4754          10 :   void increment() { number_of_weak_calls_++; }
    4755             :   int NumberOfWeakCalls() { return number_of_weak_calls_; }
    4756             : 
    4757             :  private:
    4758             :   int id_;
    4759             :   int number_of_weak_calls_;
    4760             : };
    4761             : 
    4762             : 
    4763             : template <typename T>
    4764             : struct WeakCallCounterAndPersistent {
    4765             :   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
    4766          10 :       : counter(counter) {}
    4767             :   WeakCallCounter* counter;
    4768             :   v8::Persistent<T> handle;
    4769             : };
    4770             : 
    4771             : 
    4772             : template <typename T>
    4773          10 : static void WeakPointerCallback(
    4774          20 :     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
    4775          10 :   CHECK_EQ(1234, data.GetParameter()->counter->id());
    4776             :   data.GetParameter()->counter->increment();
    4777             :   data.GetParameter()->handle.Reset();
    4778          10 : }
    4779             : 
    4780       28343 : THREADED_TEST(ScriptException) {
    4781           6 :   LocalContext env;
    4782          12 :   v8::HandleScope scope(env->GetIsolate());
    4783             :   Local<Script> script = v8_compile("throw 'panama!';");
    4784          12 :   v8::TryCatch try_catch(env->GetIsolate());
    4785           6 :   v8::MaybeLocal<Value> result = script->Run(env.local());
    4786           6 :   CHECK(result.IsEmpty());
    4787           6 :   CHECK(try_catch.HasCaught());
    4788          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    4789          12 :   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
    4790           6 : }
    4791             : 
    4792             : 
    4793       28342 : TEST(TryCatchCustomException) {
    4794           5 :   LocalContext env;
    4795           5 :   v8::Isolate* isolate = env->GetIsolate();
    4796          10 :   v8::HandleScope scope(isolate);
    4797          10 :   v8::TryCatch try_catch(isolate);
    4798             :   CompileRun(
    4799             :       "function CustomError() { this.a = 'b'; }"
    4800             :       "(function f() { throw new CustomError(); })();");
    4801           5 :   CHECK(try_catch.HasCaught());
    4802          35 :   CHECK(try_catch.Exception()
    4803             :             ->ToObject(env.local())
    4804             :             .ToLocalChecked()
    4805             :             ->Get(env.local(), v8_str("a"))
    4806             :             .ToLocalChecked()
    4807             :             ->Equals(env.local(), v8_str("b"))
    4808           5 :             .FromJust());
    4809           5 : }
    4810             : 
    4811             : 
    4812             : bool message_received;
    4813             : 
    4814             : 
    4815           6 : static void check_message_0(v8::Local<v8::Message> message,
    4816             :                             v8::Local<Value> data) {
    4817          18 :   CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
    4818             :                      .FromJust());
    4819          12 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4820             :                      .ResourceName()
    4821             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4822             :                      .FromJust());
    4823           6 :   CHECK(!message->IsSharedCrossOrigin());
    4824           6 :   message_received = true;
    4825           6 : }
    4826             : 
    4827             : 
    4828       28343 : THREADED_TEST(MessageHandler0) {
    4829           6 :   message_received = false;
    4830           6 :   v8::HandleScope scope(CcTest::isolate());
    4831           6 :   CHECK(!message_received);
    4832          12 :   LocalContext context;
    4833           6 :   CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
    4834           6 :   v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
    4835          18 :   CHECK(script->Run(context.local()).IsEmpty());
    4836           6 :   CHECK(message_received);
    4837             :   // clear out the message listener
    4838          12 :   CcTest::isolate()->RemoveMessageListeners(check_message_0);
    4839           6 : }
    4840             : 
    4841             : 
    4842           5 : static void check_message_1(v8::Local<v8::Message> message,
    4843             :                             v8::Local<Value> data) {
    4844           5 :   CHECK(data->IsNumber());
    4845          10 :   CHECK_EQ(1337,
    4846             :            data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
    4847           5 :   CHECK(!message->IsSharedCrossOrigin());
    4848           5 :   message_received = true;
    4849           5 : }
    4850             : 
    4851             : 
    4852       28342 : TEST(MessageHandler1) {
    4853           5 :   message_received = false;
    4854           5 :   v8::HandleScope scope(CcTest::isolate());
    4855           5 :   CHECK(!message_received);
    4856           5 :   CcTest::isolate()->AddMessageListener(check_message_1);
    4857          10 :   LocalContext context;
    4858             :   CompileRun("throw 1337;");
    4859           5 :   CHECK(message_received);
    4860             :   // clear out the message listener
    4861          10 :   CcTest::isolate()->RemoveMessageListeners(check_message_1);
    4862           5 : }
    4863             : 
    4864             : 
    4865           5 : static void check_message_2(v8::Local<v8::Message> message,
    4866             :                             v8::Local<Value> data) {
    4867           5 :   LocalContext context;
    4868           5 :   CHECK(data->IsObject());
    4869             :   v8::Local<v8::Value> hidden_property =
    4870             :       v8::Object::Cast(*data)
    4871             :           ->GetPrivate(
    4872             :               context.local(),
    4873           5 :               v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
    4874          10 :           .ToLocalChecked();
    4875          15 :   CHECK(v8_str("hidden value")
    4876             :             ->Equals(context.local(), hidden_property)
    4877             :             .FromJust());
    4878           5 :   CHECK(!message->IsSharedCrossOrigin());
    4879           5 :   message_received = true;
    4880           5 : }
    4881             : 
    4882             : 
    4883       28342 : TEST(MessageHandler2) {
    4884           5 :   message_received = false;
    4885           5 :   v8::HandleScope scope(CcTest::isolate());
    4886           5 :   CHECK(!message_received);
    4887           5 :   CcTest::isolate()->AddMessageListener(check_message_2);
    4888          10 :   LocalContext context;
    4889           5 :   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
    4890             :   v8::Object::Cast(*error)
    4891             :       ->SetPrivate(context.local(),
    4892             :                    v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
    4893          15 :                    v8_str("hidden value"))
    4894          10 :       .FromJust();
    4895          25 :   CHECK(context->Global()
    4896             :             ->Set(context.local(), v8_str("error"), error)
    4897             :             .FromJust());
    4898             :   CompileRun("throw error;");
    4899           5 :   CHECK(message_received);
    4900             :   // clear out the message listener
    4901          10 :   CcTest::isolate()->RemoveMessageListeners(check_message_2);
    4902           5 : }
    4903             : 
    4904             : 
    4905           5 : static void check_message_3(v8::Local<v8::Message> message,
    4906             :                             v8::Local<Value> data) {
    4907           5 :   CHECK(message->IsSharedCrossOrigin());
    4908          10 :   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
    4909          10 :   CHECK(message->GetScriptOrigin().Options().IsOpaque());
    4910          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4911             :                      .ResourceName()
    4912             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4913             :                      .FromJust());
    4914          10 :   CHECK_EQ(7.40, message->GetScriptOrigin()
    4915             :                      .SourceMapUrl()
    4916             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4917             :                      .FromJust());
    4918           5 :   message_received = true;
    4919           5 : }
    4920             : 
    4921             : 
    4922       28342 : TEST(MessageHandler3) {
    4923           5 :   message_received = false;
    4924           5 :   v8::Isolate* isolate = CcTest::isolate();
    4925           5 :   v8::HandleScope scope(isolate);
    4926           5 :   CHECK(!message_received);
    4927           5 :   isolate->AddMessageListener(check_message_3);
    4928          10 :   LocalContext context;
    4929             :   v8::ScriptOrigin origin =
    4930             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4931             :                        v8::Integer::New(isolate, 2), v8::True(isolate),
    4932           5 :                        Local<v8::Integer>(), v8_str("7.40"), v8::True(isolate));
    4933             :   v8::Local<v8::Script> script =
    4934           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4935           5 :           .ToLocalChecked();
    4936          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4937           5 :   CHECK(message_received);
    4938             :   // clear out the message listener
    4939          10 :   isolate->RemoveMessageListeners(check_message_3);
    4940           5 : }
    4941             : 
    4942             : 
    4943           5 : static void check_message_4(v8::Local<v8::Message> message,
    4944             :                             v8::Local<Value> data) {
    4945           5 :   CHECK(!message->IsSharedCrossOrigin());
    4946          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4947             :                      .ResourceName()
    4948             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4949             :                      .FromJust());
    4950           5 :   message_received = true;
    4951           5 : }
    4952             : 
    4953             : 
    4954       28342 : TEST(MessageHandler4) {
    4955           5 :   message_received = false;
    4956           5 :   v8::Isolate* isolate = CcTest::isolate();
    4957           5 :   v8::HandleScope scope(isolate);
    4958           5 :   CHECK(!message_received);
    4959           5 :   isolate->AddMessageListener(check_message_4);
    4960          10 :   LocalContext context;
    4961             :   v8::ScriptOrigin origin =
    4962             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4963           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    4964             :   v8::Local<v8::Script> script =
    4965           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4966           5 :           .ToLocalChecked();
    4967          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4968           5 :   CHECK(message_received);
    4969             :   // clear out the message listener
    4970          10 :   isolate->RemoveMessageListeners(check_message_4);
    4971           5 : }
    4972             : 
    4973             : 
    4974           5 : static void check_message_5a(v8::Local<v8::Message> message,
    4975             :                              v8::Local<Value> data) {
    4976           5 :   CHECK(message->IsSharedCrossOrigin());
    4977          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4978             :                      .ResourceName()
    4979             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4980             :                      .FromJust());
    4981           5 :   message_received = true;
    4982           5 : }
    4983             : 
    4984             : 
    4985           5 : static void check_message_5b(v8::Local<v8::Message> message,
    4986             :                              v8::Local<Value> data) {
    4987           5 :   CHECK(!message->IsSharedCrossOrigin());
    4988          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4989             :                      .ResourceName()
    4990             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4991             :                      .FromJust());
    4992           5 :   message_received = true;
    4993           5 : }
    4994             : 
    4995             : 
    4996       28342 : TEST(MessageHandler5) {
    4997           5 :   message_received = false;
    4998           5 :   v8::Isolate* isolate = CcTest::isolate();
    4999           5 :   v8::HandleScope scope(isolate);
    5000           5 :   CHECK(!message_received);
    5001           5 :   isolate->AddMessageListener(check_message_5a);
    5002          10 :   LocalContext context;
    5003             :   v8::ScriptOrigin origin1 =
    5004             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    5005           5 :                        v8::Integer::New(isolate, 2), v8::True(isolate));
    5006             :   v8::Local<v8::Script> script =
    5007           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
    5008           5 :           .ToLocalChecked();
    5009          10 :   CHECK(script->Run(context.local()).IsEmpty());
    5010           5 :   CHECK(message_received);
    5011             :   // clear out the message listener
    5012           5 :   isolate->RemoveMessageListeners(check_message_5a);
    5013             : 
    5014           5 :   message_received = false;
    5015           5 :   isolate->AddMessageListener(check_message_5b);
    5016             :   v8::ScriptOrigin origin2 =
    5017             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    5018           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    5019           5 :   script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
    5020           5 :                .ToLocalChecked();
    5021          10 :   CHECK(script->Run(context.local()).IsEmpty());
    5022           5 :   CHECK(message_received);
    5023             :   // clear out the message listener
    5024          10 :   isolate->RemoveMessageListeners(check_message_5b);
    5025           5 : }
    5026             : 
    5027             : 
    5028       28343 : THREADED_TEST(GetSetProperty) {
    5029           6 :   LocalContext context;
    5030           6 :   v8::Isolate* isolate = context->GetIsolate();
    5031          12 :   v8::HandleScope scope(isolate);
    5032          30 :   CHECK(context->Global()
    5033             :             ->Set(context.local(), v8_str("foo"), v8_num(14))
    5034             :             .FromJust());
    5035          30 :   CHECK(context->Global()
    5036             :             ->Set(context.local(), v8_str("12"), v8_num(92))
    5037             :             .FromJust());
    5038          30 :   CHECK(context->Global()
    5039             :             ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
    5040             :             .FromJust());
    5041          24 :   CHECK(context->Global()
    5042             :             ->Set(context.local(), v8_num(13), v8_num(56))
    5043             :             .FromJust());
    5044             :   Local<Value> foo = CompileRun("this.foo");
    5045          12 :   CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
    5046             :   Local<Value> twelve = CompileRun("this[12]");
    5047          12 :   CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
    5048             :   Local<Value> sixteen = CompileRun("this[16]");
    5049          12 :   CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
    5050             :   Local<Value> thirteen = CompileRun("this[13]");
    5051          12 :   CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
    5052          36 :   CHECK_EQ(92, context->Global()
    5053             :                    ->Get(context.local(), v8::Integer::New(isolate, 12))
    5054             :                    .ToLocalChecked()
    5055             :                    ->Int32Value(context.local())
    5056             :                    .FromJust());
    5057          36 :   CHECK_EQ(92, context->Global()
    5058             :                    ->Get(context.local(), v8_str("12"))
    5059             :                    .ToLocalChecked()
    5060             :                    ->Int32Value(context.local())
    5061             :                    .FromJust());
    5062          30 :   CHECK_EQ(92, context->Global()
    5063             :                    ->Get(context.local(), v8_num(12))
    5064             :                    .ToLocalChecked()
    5065             :                    ->Int32Value(context.local())
    5066             :                    .FromJust());
    5067          36 :   CHECK_EQ(32, context->Global()
    5068             :                    ->Get(context.local(), v8::Integer::New(isolate, 16))
    5069             :                    .ToLocalChecked()
    5070             :                    ->Int32Value(context.local())
    5071             :                    .FromJust());
    5072          36 :   CHECK_EQ(32, context->Global()
    5073             :                    ->Get(context.local(), v8_str("16"))
    5074             :                    .ToLocalChecked()
    5075             :                    ->Int32Value(context.local())
    5076             :                    .FromJust());
    5077          30 :   CHECK_EQ(32, context->Global()
    5078             :                    ->Get(context.local(), v8_num(16))
    5079             :                    .ToLocalChecked()
    5080             :                    ->Int32Value(context.local())
    5081             :                    .FromJust());
    5082          36 :   CHECK_EQ(56, context->Global()
    5083             :                    ->Get(context.local(), v8::Integer::New(isolate, 13))
    5084             :                    .ToLocalChecked()
    5085             :                    ->Int32Value(context.local())
    5086             :                    .FromJust());
    5087          36 :   CHECK_EQ(56, context->Global()
    5088             :                    ->Get(context.local(), v8_str("13"))
    5089             :                    .ToLocalChecked()
    5090             :                    ->Int32Value(context.local())
    5091             :                    .FromJust());
    5092          30 :   CHECK_EQ(56, context->Global()
    5093             :                    ->Get(context.local(), v8_num(13))
    5094             :                    .ToLocalChecked()
    5095             :                    ->Int32Value(context.local())
    5096           6 :                    .FromJust());
    5097           6 : }
    5098             : 
    5099             : 
    5100       28343 : THREADED_TEST(PropertyAttributes) {
    5101           6 :   LocalContext context;
    5102          12 :   v8::HandleScope scope(context->GetIsolate());
    5103             :   // none
    5104           6 :   Local<String> prop = v8_str("none");
    5105          30 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
    5106          24 :   CHECK_EQ(v8::None, context->Global()
    5107             :                          ->GetPropertyAttributes(context.local(), prop)
    5108             :                          .FromJust());
    5109             :   // read-only
    5110           6 :   prop = v8_str("read_only");
    5111             :   context->Global()
    5112          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
    5113          12 :       .FromJust();
    5114          36 :   CHECK_EQ(7, context->Global()
    5115             :                   ->Get(context.local(), prop)
    5116             :                   .ToLocalChecked()
    5117             :                   ->Int32Value(context.local())
    5118             :                   .FromJust());
    5119          24 :   CHECK_EQ(v8::ReadOnly, context->Global()
    5120             :                              ->GetPropertyAttributes(context.local(), prop)
    5121             :                              .FromJust());
    5122             :   CompileRun("read_only = 9");
    5123          36 :   CHECK_EQ(7, context->Global()
    5124             :                   ->Get(context.local(), prop)
    5125             :                   .ToLocalChecked()
    5126             :                   ->Int32Value(context.local())
    5127             :                   .FromJust());
    5128          30 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
    5129          36 :   CHECK_EQ(7, context->Global()
    5130             :                   ->Get(context.local(), prop)
    5131             :                   .ToLocalChecked()
    5132             :                   ->Int32Value(context.local())
    5133             :                   .FromJust());
    5134             :   // dont-delete
    5135           6 :   prop = v8_str("dont_delete");
    5136             :   context->Global()
    5137          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
    5138          12 :       .FromJust();
    5139          36 :   CHECK_EQ(13, context->Global()
    5140             :                    ->Get(context.local(), prop)
    5141             :                    .ToLocalChecked()
    5142             :                    ->Int32Value(context.local())
    5143             :                    .FromJust());
    5144             :   CompileRun("delete dont_delete");
    5145          36 :   CHECK_EQ(13, context->Global()
    5146             :                    ->Get(context.local(), prop)
    5147             :                    .ToLocalChecked()
    5148             :                    ->Int32Value(context.local())
    5149             :                    .FromJust());
    5150          24 :   CHECK_EQ(v8::DontDelete, context->Global()
    5151             :                                ->GetPropertyAttributes(context.local(), prop)
    5152             :                                .FromJust());
    5153             :   // dont-enum
    5154           6 :   prop = v8_str("dont_enum");
    5155             :   context->Global()
    5156          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
    5157          12 :       .FromJust();
    5158          24 :   CHECK_EQ(v8::DontEnum, context->Global()
    5159             :                              ->GetPropertyAttributes(context.local(), prop)
    5160             :                              .FromJust());
    5161             :   // absent
    5162           6 :   prop = v8_str("absent");
    5163          24 :   CHECK_EQ(v8::None, context->Global()
    5164             :                          ->GetPropertyAttributes(context.local(), prop)
    5165             :                          .FromJust());
    5166           6 :   Local<Value> fake_prop = v8_num(1);
    5167          24 :   CHECK_EQ(v8::None, context->Global()
    5168             :                          ->GetPropertyAttributes(context.local(), fake_prop)
    5169             :                          .FromJust());
    5170             :   // exception
    5171          12 :   TryCatch try_catch(context->GetIsolate());
    5172             :   Local<Value> exception =
    5173           6 :       CompileRun("({ toString: function() { throw 'exception';} })");
    5174          24 :   CHECK(context->Global()
    5175             :             ->GetPropertyAttributes(context.local(), exception)
    5176             :             .IsNothing());
    5177           6 :   CHECK(try_catch.HasCaught());
    5178             :   String::Utf8Value exception_value(context->GetIsolate(),
    5179          18 :                                     try_catch.Exception());
    5180           6 :   CHECK_EQ(0, strcmp("exception", *exception_value));
    5181          12 :   try_catch.Reset();
    5182           6 : }
    5183             : 
    5184             : 
    5185       28343 : THREADED_TEST(Array) {
    5186           6 :   LocalContext context;
    5187          12 :   v8::HandleScope scope(context->GetIsolate());
    5188           6 :   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
    5189           6 :   CHECK_EQ(0u, array->Length());
    5190          12 :   CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
    5191          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5192          12 :   CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
    5193          12 :   CHECK(!array->Has(context.local(), 100).FromJust());
    5194          12 :   CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
    5195           6 :   CHECK_EQ(3u, array->Length());
    5196          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5197          12 :   CHECK(!array->Has(context.local(), 1).FromJust());
    5198          12 :   CHECK(array->Has(context.local(), 2).FromJust());
    5199          18 :   CHECK_EQ(7, array->Get(context.local(), 2)
    5200             :                   .ToLocalChecked()
    5201             :                   ->Int32Value(context.local())
    5202             :                   .FromJust());
    5203             :   Local<Value> obj = CompileRun("[1, 2, 3]");
    5204             :   Local<v8::Array> arr = obj.As<v8::Array>();
    5205           6 :   CHECK_EQ(3u, arr->Length());
    5206          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5207             :                   .ToLocalChecked()
    5208             :                   ->Int32Value(context.local())
    5209             :                   .FromJust());
    5210          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5211             :                   .ToLocalChecked()
    5212             :                   ->Int32Value(context.local())
    5213             :                   .FromJust());
    5214          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5215             :                   .ToLocalChecked()
    5216             :                   ->Int32Value(context.local())
    5217             :                   .FromJust());
    5218           6 :   array = v8::Array::New(context->GetIsolate(), 27);
    5219           6 :   CHECK_EQ(27u, array->Length());
    5220           6 :   array = v8::Array::New(context->GetIsolate(), -27);
    5221           6 :   CHECK_EQ(0u, array->Length());
    5222             : 
    5223          12 :   std::vector<Local<Value>> vector = {v8_num(1), v8_num(2), v8_num(3)};
    5224          12 :   array = v8::Array::New(context->GetIsolate(), vector.data(), vector.size());
    5225          12 :   CHECK_EQ(vector.size(), array->Length());
    5226          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5227             :                   .ToLocalChecked()
    5228             :                   ->Int32Value(context.local())
    5229             :                   .FromJust());
    5230          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5231             :                   .ToLocalChecked()
    5232             :                   ->Int32Value(context.local())
    5233             :                   .FromJust());
    5234          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5235             :                   .ToLocalChecked()
    5236             :                   ->Int32Value(context.local())
    5237           6 :                   .FromJust());
    5238           6 : }
    5239             : 
    5240             : 
    5241         180 : void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5242          30 :   v8::EscapableHandleScope scope(args.GetIsolate());
    5243          30 :   ApiTestFuzzer::Fuzz();
    5244          30 :   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
    5245         180 :   for (int i = 0; i < args.Length(); i++) {
    5246         180 :     CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
    5247             :               .FromJust());
    5248             :   }
    5249             :   args.GetReturnValue().Set(scope.Escape(result));
    5250          30 : }
    5251             : 
    5252             : 
    5253       28343 : THREADED_TEST(Vector) {
    5254           6 :   v8::Isolate* isolate = CcTest::isolate();
    5255           6 :   v8::HandleScope scope(isolate);
    5256           6 :   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
    5257          18 :   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
    5258          12 :   LocalContext context(nullptr, global);
    5259             : 
    5260             :   const char* fun = "f()";
    5261             :   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
    5262           6 :   CHECK_EQ(0u, a0->Length());
    5263             : 
    5264             :   const char* fun2 = "f(11)";
    5265             :   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
    5266           6 :   CHECK_EQ(1u, a1->Length());
    5267          18 :   CHECK_EQ(11, a1->Get(context.local(), 0)
    5268             :                    .ToLocalChecked()
    5269             :                    ->Int32Value(context.local())
    5270             :                    .FromJust());
    5271             : 
    5272             :   const char* fun3 = "f(12, 13)";
    5273             :   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
    5274           6 :   CHECK_EQ(2u, a2->Length());
    5275          18 :   CHECK_EQ(12, a2->Get(context.local(), 0)
    5276             :                    .ToLocalChecked()
    5277             :                    ->Int32Value(context.local())
    5278             :                    .FromJust());
    5279          18 :   CHECK_EQ(13, a2->Get(context.local(), 1)
    5280             :                    .ToLocalChecked()
    5281             :                    ->Int32Value(context.local())
    5282             :                    .FromJust());
    5283             : 
    5284             :   const char* fun4 = "f(14, 15, 16)";
    5285             :   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
    5286           6 :   CHECK_EQ(3u, a3->Length());
    5287          18 :   CHECK_EQ(14, a3->Get(context.local(), 0)
    5288             :                    .ToLocalChecked()
    5289             :                    ->Int32Value(context.local())
    5290             :                    .FromJust());
    5291          18 :   CHECK_EQ(15, a3->Get(context.local(), 1)
    5292             :                    .ToLocalChecked()
    5293             :                    ->Int32Value(context.local())
    5294             :                    .FromJust());
    5295          18 :   CHECK_EQ(16, a3->Get(context.local(), 2)
    5296             :                    .ToLocalChecked()
    5297             :                    ->Int32Value(context.local())
    5298             :                    .FromJust());
    5299             : 
    5300             :   const char* fun5 = "f(17, 18, 19, 20)";
    5301             :   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
    5302           6 :   CHECK_EQ(4u, a4->Length());
    5303          18 :   CHECK_EQ(17, a4->Get(context.local(), 0)
    5304             :                    .ToLocalChecked()
    5305             :                    ->Int32Value(context.local())
    5306             :                    .FromJust());
    5307          18 :   CHECK_EQ(18, a4->Get(context.local(), 1)
    5308             :                    .ToLocalChecked()
    5309             :                    ->Int32Value(context.local())
    5310             :                    .FromJust());
    5311          18 :   CHECK_EQ(19, a4->Get(context.local(), 2)
    5312             :                    .ToLocalChecked()
    5313             :                    ->Int32Value(context.local())
    5314             :                    .FromJust());
    5315          18 :   CHECK_EQ(20, a4->Get(context.local(), 3)
    5316             :                    .ToLocalChecked()
    5317             :                    ->Int32Value(context.local())
    5318           6 :                    .FromJust());
    5319           6 : }
    5320             : 
    5321             : 
    5322       28343 : THREADED_TEST(FunctionCall) {
    5323           6 :   LocalContext context;
    5324           6 :   v8::Isolate* isolate = context->GetIsolate();
    5325          12 :   v8::HandleScope scope(isolate);
    5326             :   CompileRun(
    5327             :       "function Foo() {"
    5328             :       "  var result = [];"
    5329             :       "  for (var i = 0; i < arguments.length; i++) {"
    5330             :       "    result.push(arguments[i]);"
    5331             :       "  }"
    5332             :       "  return result;"
    5333             :       "}"
    5334             :       "function ReturnThisSloppy() {"
    5335             :       "  return this;"
    5336             :       "}"
    5337             :       "function ReturnThisStrict() {"
    5338             :       "  'use strict';"
    5339             :       "  return this;"
    5340             :       "}");
    5341             :   Local<Function> Foo = Local<Function>::Cast(
    5342          30 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5343             :   Local<Function> ReturnThisSloppy = Local<Function>::Cast(
    5344             :       context->Global()
    5345          24 :           ->Get(context.local(), v8_str("ReturnThisSloppy"))
    5346           6 :           .ToLocalChecked());
    5347             :   Local<Function> ReturnThisStrict = Local<Function>::Cast(
    5348             :       context->Global()
    5349          24 :           ->Get(context.local(), v8_str("ReturnThisStrict"))
    5350           6 :           .ToLocalChecked());
    5351             : 
    5352             :   v8::Local<Value>* args0 = nullptr;
    5353             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5354          12 :       Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
    5355           6 :   CHECK_EQ(0u, a0->Length());
    5356             : 
    5357           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5358             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5359          12 :       Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
    5360           6 :   CHECK_EQ(1u, a1->Length());
    5361          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5362             :                     .ToLocalChecked()
    5363             :                     ->NumberValue(context.local())
    5364             :                     .FromJust());
    5365             : 
    5366           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5367             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5368          12 :       Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
    5369           6 :   CHECK_EQ(2u, a2->Length());
    5370          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5371             :                     .ToLocalChecked()
    5372             :                     ->NumberValue(context.local())
    5373             :                     .FromJust());
    5374          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5375             :                     .ToLocalChecked()
    5376             :                     ->NumberValue(context.local())
    5377             :                     .FromJust());
    5378             : 
    5379           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5380             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5381          12 :       Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
    5382           6 :   CHECK_EQ(3u, a3->Length());
    5383          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5384             :                     .ToLocalChecked()
    5385             :                     ->NumberValue(context.local())
    5386             :                     .FromJust());
    5387          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5388             :                     .ToLocalChecked()
    5389             :                     ->NumberValue(context.local())
    5390             :                     .FromJust());
    5391          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5392             :                     .ToLocalChecked()
    5393             :                     ->NumberValue(context.local())
    5394             :                     .FromJust());
    5395             : 
    5396             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5397           6 :                               v8_num(10.11)};
    5398             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5399          12 :       Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
    5400           6 :   CHECK_EQ(4u, a4->Length());
    5401          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5402             :                     .ToLocalChecked()
    5403             :                     ->NumberValue(context.local())
    5404             :                     .FromJust());
    5405          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5406             :                     .ToLocalChecked()
    5407             :                     ->NumberValue(context.local())
    5408             :                     .FromJust());
    5409          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5410             :                     .ToLocalChecked()
    5411             :                     ->NumberValue(context.local())
    5412             :                     .FromJust());
    5413          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5414             :                       .ToLocalChecked()
    5415             :                       ->NumberValue(context.local())
    5416             :                       .FromJust());
    5417             : 
    5418             :   Local<v8::Value> r1 =
    5419             :       ReturnThisSloppy
    5420          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5421           6 :           .ToLocalChecked();
    5422          12 :   CHECK(r1->StrictEquals(context->Global()));
    5423             :   Local<v8::Value> r2 =
    5424          12 :       ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5425           6 :           .ToLocalChecked();
    5426          12 :   CHECK(r2->StrictEquals(context->Global()));
    5427             :   Local<v8::Value> r3 =
    5428           6 :       ReturnThisSloppy->Call(context.local(), v8_num(42), 0, nullptr)
    5429           6 :           .ToLocalChecked();
    5430           6 :   CHECK(r3->IsNumberObject());
    5431           6 :   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
    5432             :   Local<v8::Value> r4 =
    5433          18 :       ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, nullptr)
    5434           6 :           .ToLocalChecked();
    5435           6 :   CHECK(r4->IsStringObject());
    5436          18 :   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
    5437             :   Local<v8::Value> r5 =
    5438          12 :       ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, nullptr)
    5439           6 :           .ToLocalChecked();
    5440           6 :   CHECK(r5->IsBooleanObject());
    5441           6 :   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
    5442             : 
    5443             :   Local<v8::Value> r6 =
    5444             :       ReturnThisStrict
    5445          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5446           6 :           .ToLocalChecked();
    5447           6 :   CHECK(r6->IsUndefined());
    5448             :   Local<v8::Value> r7 =
    5449          12 :       ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5450           6 :           .ToLocalChecked();
    5451           6 :   CHECK(r7->IsNull());
    5452             :   Local<v8::Value> r8 =
    5453           6 :       ReturnThisStrict->Call(context.local(), v8_num(42), 0, nullptr)
    5454           6 :           .ToLocalChecked();
    5455           6 :   CHECK(r8->StrictEquals(v8_num(42)));
    5456             :   Local<v8::Value> r9 =
    5457          18 :       ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, nullptr)
    5458           6 :           .ToLocalChecked();
    5459          12 :   CHECK(r9->StrictEquals(v8_str("hello")));
    5460             :   Local<v8::Value> r10 =
    5461          12 :       ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, nullptr)
    5462           6 :           .ToLocalChecked();
    5463          12 :   CHECK(r10->StrictEquals(v8::True(isolate)));
    5464           6 : }
    5465             : 
    5466             : 
    5467       28343 : THREADED_TEST(ConstructCall) {
    5468           6 :   LocalContext context;
    5469           6 :   v8::Isolate* isolate = context->GetIsolate();
    5470          12 :   v8::HandleScope scope(isolate);
    5471             :   CompileRun(
    5472             :       "function Foo() {"
    5473             :       "  var result = [];"
    5474             :       "  for (var i = 0; i < arguments.length; i++) {"
    5475             :       "    result.push(arguments[i]);"
    5476             :       "  }"
    5477             :       "  return result;"
    5478             :       "}");
    5479             :   Local<Function> Foo = Local<Function>::Cast(
    5480          30 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5481             : 
    5482             :   v8::Local<Value>* args0 = nullptr;
    5483             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5484           6 :       Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
    5485           6 :   CHECK_EQ(0u, a0->Length());
    5486             : 
    5487           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5488             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5489           6 :       Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
    5490           6 :   CHECK_EQ(1u, a1->Length());
    5491          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5492             :                     .ToLocalChecked()
    5493             :                     ->NumberValue(context.local())
    5494             :                     .FromJust());
    5495             : 
    5496           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5497             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5498           6 :       Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
    5499           6 :   CHECK_EQ(2u, a2->Length());
    5500          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5501             :                     .ToLocalChecked()
    5502             :                     ->NumberValue(context.local())
    5503             :                     .FromJust());
    5504          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5505             :                     .ToLocalChecked()
    5506             :                     ->NumberValue(context.local())
    5507             :                     .FromJust());
    5508             : 
    5509           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5510             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5511           6 :       Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
    5512           6 :   CHECK_EQ(3u, a3->Length());
    5513          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5514             :                     .ToLocalChecked()
    5515             :                     ->NumberValue(context.local())
    5516             :                     .FromJust());
    5517          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5518             :                     .ToLocalChecked()
    5519             :                     ->NumberValue(context.local())
    5520             :                     .FromJust());
    5521          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5522             :                     .ToLocalChecked()
    5523             :                     ->NumberValue(context.local())
    5524             :                     .FromJust());
    5525             : 
    5526             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5527           6 :                               v8_num(10.11)};
    5528             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5529           6 :       Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
    5530           6 :   CHECK_EQ(4u, a4->Length());
    5531          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5532             :                     .ToLocalChecked()
    5533             :                     ->NumberValue(context.local())
    5534             :                     .FromJust());
    5535          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5536             :                     .ToLocalChecked()
    5537             :                     ->NumberValue(context.local())
    5538             :                     .FromJust());
    5539          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5540             :                     .ToLocalChecked()
    5541             :                     ->NumberValue(context.local())
    5542             :                     .FromJust());
    5543          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5544             :                       .ToLocalChecked()
    5545             :                       ->NumberValue(context.local())
    5546           6 :                       .FromJust());
    5547           6 : }
    5548             : 
    5549             : 
    5550       28343 : THREADED_TEST(ConversionNumber) {
    5551           6 :   LocalContext env;
    5552           6 :   v8::Isolate* isolate = env->GetIsolate();
    5553          12 :   v8::HandleScope scope(isolate);
    5554             :   // Very large number.
    5555             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5556             :   Local<Value> obj =
    5557          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5558          12 :   CHECK_EQ(5312874545152.0,
    5559             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5560          12 :   CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5561          12 :   CHECK_EQ(0, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5562             :   // Large number.
    5563             :   CompileRun("var obj = -1234567890123;");
    5564          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5565          12 :   CHECK_EQ(-1234567890123.0,
    5566             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5567          12 :   CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5568          18 :   CHECK_EQ(2382691125, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5569             :   // Small positive integer.
    5570             :   CompileRun("var obj = 42;");
    5571          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5572          12 :   CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5573          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5574          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5575             :   // Negative integer.
    5576             :   CompileRun("var obj = -37;");
    5577          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5578          12 :   CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5579          12 :   CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5580          18 :   CHECK_EQ(4294967259, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5581             :   // Positive non-int32 integer.
    5582             :   CompileRun("var obj = 0x81234567;");
    5583          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5584          12 :   CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5585          12 :   CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5586          18 :   CHECK_EQ(2166572391, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5587             :   // Fraction.
    5588             :   CompileRun("var obj = 42.3;");
    5589          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5590          12 :   CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5591          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5592          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5593             :   // Large negative fraction.
    5594             :   CompileRun("var obj = -5726623061.75;");
    5595          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5596          12 :   CHECK_EQ(-5726623061.75,
    5597             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5598          12 :   CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5599          24 :   CHECK_EQ(2863311531, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5600           6 : }
    5601             : 
    5602             : 
    5603       28343 : THREADED_TEST(isNumberType) {
    5604           6 :   LocalContext env;
    5605          12 :   v8::HandleScope scope(env->GetIsolate());
    5606             :   // Very large number.
    5607             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5608             :   Local<Value> obj =
    5609          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5610           6 :   CHECK(!obj->IsInt32());
    5611           6 :   CHECK(!obj->IsUint32());
    5612             :   // Large negative number.
    5613             :   CompileRun("var obj = -1234567890123;");
    5614          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5615           6 :   CHECK(!obj->IsInt32());
    5616           6 :   CHECK(!obj->IsUint32());
    5617             :   // Small positive integer.
    5618             :   CompileRun("var obj = 42;");
    5619          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5620           6 :   CHECK(obj->IsInt32());
    5621           6 :   CHECK(obj->IsUint32());
    5622             :   // Negative integer.
    5623             :   CompileRun("var obj = -37;");
    5624          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5625           6 :   CHECK(obj->IsInt32());
    5626           6 :   CHECK(!obj->IsUint32());
    5627             :   // Positive non-int32 integer.
    5628             :   CompileRun("var obj = 0x81234567;");
    5629          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5630           6 :   CHECK(!obj->IsInt32());
    5631           6 :   CHECK(obj->IsUint32());
    5632             :   // Fraction.
    5633             :   CompileRun("var obj = 42.3;");
    5634          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5635           6 :   CHECK(!obj->IsInt32());
    5636           6 :   CHECK(!obj->IsUint32());
    5637             :   // Large negative fraction.
    5638             :   CompileRun("var obj = -5726623061.75;");
    5639          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5640           6 :   CHECK(!obj->IsInt32());
    5641           6 :   CHECK(!obj->IsUint32());
    5642             :   // Positive zero
    5643             :   CompileRun("var obj = 0.0;");
    5644          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5645           6 :   CHECK(obj->IsInt32());
    5646           6 :   CHECK(obj->IsUint32());
    5647             :   // Negative zero
    5648             :   CompileRun("var obj = -0.0;");
    5649          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5650           6 :   CHECK(!obj->IsInt32());
    5651          12 :   CHECK(!obj->IsUint32());
    5652           6 : }
    5653             : 
    5654       28343 : THREADED_TEST(IntegerType) {
    5655           6 :   LocalContext env;
    5656          12 :   v8::HandleScope scope(env->GetIsolate());
    5657             :   Local<Value> result;
    5658             : 
    5659             :   // Small positive integer
    5660             :   result = CompileRun("42;");
    5661           6 :   CHECK(result->IsNumber());
    5662           6 :   CHECK_EQ(42, result.As<v8::Integer>()->Value());
    5663             :   // Small negative integer
    5664             :   result = CompileRun("-42;");
    5665           6 :   CHECK(result->IsNumber());
    5666           6 :   CHECK_EQ(-42, result.As<v8::Integer>()->Value());
    5667             :   // Positive non-int32 integer
    5668             :   result = CompileRun("1099511627776;");
    5669           6 :   CHECK(result->IsNumber());
    5670           6 :   CHECK_EQ(1099511627776, result.As<v8::Integer>()->Value());
    5671             :   // Negative non-int32 integer
    5672             :   result = CompileRun("-1099511627776;");
    5673           6 :   CHECK(result->IsNumber());
    5674           6 :   CHECK_EQ(-1099511627776, result.As<v8::Integer>()->Value());
    5675             :   // Positive non-integer
    5676             :   result = CompileRun("3.14;");
    5677           6 :   CHECK(result->IsNumber());
    5678           6 :   CHECK_EQ(3, result.As<v8::Integer>()->Value());
    5679             :   // Negative non-integer
    5680             :   result = CompileRun("-3.14;");
    5681           6 :   CHECK(result->IsNumber());
    5682          12 :   CHECK_EQ(-3, result.As<v8::Integer>()->Value());
    5683           6 : }
    5684             : 
    5685          54 : static void CheckUncle(v8::Isolate* isolate, v8::TryCatch* try_catch) {
    5686          54 :   CHECK(try_catch->HasCaught());
    5687          54 :   String::Utf8Value str_value(isolate, try_catch->Exception());
    5688          54 :   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
    5689          54 :   try_catch->Reset();
    5690          54 : }
    5691             : 
    5692       28343 : THREADED_TEST(ConversionException) {
    5693           6 :   LocalContext env;
    5694           6 :   v8::Isolate* isolate = env->GetIsolate();
    5695          12 :   v8::HandleScope scope(isolate);
    5696             :   CompileRun(
    5697             :       "function TestClass() { };"
    5698             :       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
    5699             :       "var obj = new TestClass();");
    5700             :   Local<Value> obj =
    5701          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5702             : 
    5703          12 :   v8::TryCatch try_catch(isolate);
    5704             : 
    5705          12 :   CHECK(obj->ToString(env.local()).IsEmpty());
    5706           6 :   CheckUncle(isolate, &try_catch);
    5707             : 
    5708          12 :   CHECK(obj->ToNumber(env.local()).IsEmpty());
    5709           6 :   CheckUncle(isolate, &try_catch);
    5710             : 
    5711          12 :   CHECK(obj->ToInteger(env.local()).IsEmpty());
    5712           6 :   CheckUncle(isolate, &try_catch);
    5713             : 
    5714          12 :   CHECK(obj->ToUint32(env.local()).IsEmpty());
    5715           6 :   CheckUncle(isolate, &try_catch);
    5716             : 
    5717          12 :   CHECK(obj->ToInt32(env.local()).IsEmpty());
    5718           6 :   CheckUncle(isolate, &try_catch);
    5719             : 
    5720          18 :   CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
    5721           6 :   CHECK(try_catch.HasCaught());
    5722           6 :   try_catch.Reset();
    5723             : 
    5724          12 :   CHECK(obj->Int32Value(env.local()).IsNothing());
    5725           6 :   CheckUncle(isolate, &try_catch);
    5726             : 
    5727          12 :   CHECK(obj->Uint32Value(env.local()).IsNothing());
    5728           6 :   CheckUncle(isolate, &try_catch);
    5729             : 
    5730          12 :   CHECK(obj->NumberValue(env.local()).IsNothing());
    5731           6 :   CheckUncle(isolate, &try_catch);
    5732             : 
    5733          12 :   CHECK(obj->IntegerValue(env.local()).IsNothing());
    5734          12 :   CheckUncle(isolate, &try_catch);
    5735           6 : }
    5736             : 
    5737             : 
    5738          56 : void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5739          28 :   ApiTestFuzzer::Fuzz();
    5740          56 :   args.GetIsolate()->ThrowException(v8_str("konto"));
    5741          28 : }
    5742             : 
    5743             : 
    5744          25 : void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5745           5 :   if (args.Length() < 1) {
    5746             :     args.GetReturnValue().Set(false);
    5747           5 :     return;
    5748             :   }
    5749           5 :   v8::HandleScope scope(args.GetIsolate());
    5750          10 :   v8::TryCatch try_catch(args.GetIsolate());
    5751             :   Local<Value> result =
    5752             :       CompileRun(args[0]
    5753           5 :                      ->ToString(args.GetIsolate()->GetCurrentContext())
    5754          10 :                      .ToLocalChecked());
    5755          10 :   CHECK(!try_catch.HasCaught() || result.IsEmpty());
    5756          10 :   args.GetReturnValue().Set(try_catch.HasCaught());
    5757             : }
    5758             : 
    5759             : 
    5760       28343 : THREADED_TEST(APICatch) {
    5761           6 :   v8::Isolate* isolate = CcTest::isolate();
    5762           6 :   v8::HandleScope scope(isolate);
    5763           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5764             :   templ->Set(v8_str("ThrowFromC"),
    5765          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5766          12 :   LocalContext context(nullptr, templ);
    5767             :   CompileRun(
    5768             :       "var thrown = false;"
    5769             :       "try {"
    5770             :       "  ThrowFromC();"
    5771             :       "} catch (e) {"
    5772             :       "  thrown = true;"
    5773             :       "}");
    5774             :   Local<Value> thrown = context->Global()
    5775          24 :                             ->Get(context.local(), v8_str("thrown"))
    5776           6 :                             .ToLocalChecked();
    5777          12 :   CHECK(thrown->BooleanValue(isolate));
    5778           6 : }
    5779             : 
    5780             : 
    5781       28343 : THREADED_TEST(APIThrowTryCatch) {
    5782           6 :   v8::Isolate* isolate = CcTest::isolate();
    5783           6 :   v8::HandleScope scope(isolate);
    5784           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5785             :   templ->Set(v8_str("ThrowFromC"),
    5786          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5787          12 :   LocalContext context(nullptr, templ);
    5788          12 :   v8::TryCatch try_catch(isolate);
    5789             :   CompileRun("ThrowFromC();");
    5790          12 :   CHECK(try_catch.HasCaught());
    5791           6 : }
    5792             : 
    5793             : 
    5794             : // Test that a try-finally block doesn't shadow a try-catch block
    5795             : // when setting up an external handler.
    5796             : //
    5797             : // BUG(271): Some of the exception propagation does not work on the
    5798             : // ARM simulator because the simulator separates the C++ stack and the
    5799             : // JS stack.  This test therefore fails on the simulator.  The test is
    5800             : // not threaded to allow the threading tests to run on the simulator.
    5801       28342 : TEST(TryCatchInTryFinally) {
    5802           5 :   v8::Isolate* isolate = CcTest::isolate();
    5803           5 :   v8::HandleScope scope(isolate);
    5804           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5805          15 :   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
    5806          10 :   LocalContext context(nullptr, templ);
    5807             :   Local<Value> result = CompileRun(
    5808             :       "try {"
    5809             :       "  try {"
    5810             :       "    CCatcher('throw 7;');"
    5811             :       "  } finally {"
    5812             :       "  }"
    5813             :       "} catch (e) {"
    5814             :       "}");
    5815          10 :   CHECK(result->IsTrue());
    5816           5 : }
    5817             : 
    5818             : 
    5819           5 : static void check_custom_error_tostring(v8::Local<v8::Message> message,
    5820             :                                         v8::Local<v8::Value> data) {
    5821             :   const char* uncaught_error = "Uncaught MyError toString";
    5822          25 :   CHECK(message->Get()
    5823             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5824             :                      v8_str(uncaught_error))
    5825             :             .FromJust());
    5826           5 : }
    5827             : 
    5828             : 
    5829       28342 : TEST(CustomErrorToString) {
    5830           5 :   LocalContext context;
    5831          10 :   v8::HandleScope scope(context->GetIsolate());
    5832           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
    5833             :   CompileRun(
    5834             :       "function MyError(name, message) {                   "
    5835             :       "  this.name = name;                                 "
    5836             :       "  this.message = message;                           "
    5837             :       "}                                                   "
    5838             :       "MyError.prototype = Object.create(Error.prototype); "
    5839             :       "MyError.prototype.toString = function() {           "
    5840             :       "  return 'MyError toString';                        "
    5841             :       "};                                                  "
    5842             :       "throw new MyError('my name', 'my message');         ");
    5843          10 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
    5844           5 : }
    5845             : 
    5846             : 
    5847          15 : static void check_custom_error_message(v8::Local<v8::Message> message,
    5848             :                                        v8::Local<v8::Value> data) {
    5849             :   const char* uncaught_error = "Uncaught MyError: my message";
    5850          45 :   printf("%s\n", *v8::String::Utf8Value(CcTest::isolate(), message->Get()));
    5851          60 :   CHECK(message->Get()
    5852             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5853             :                      v8_str(uncaught_error))
    5854             :             .FromJust());
    5855          15 : }
    5856             : 
    5857             : 
    5858       28342 : TEST(CustomErrorMessage) {
    5859           5 :   LocalContext context;
    5860          10 :   v8::HandleScope scope(context->GetIsolate());
    5861           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_message);
    5862             : 
    5863             :   // Handlebars.
    5864             :   CompileRun(
    5865             :       "function MyError(msg) {                             "
    5866             :       "  this.name = 'MyError';                            "
    5867             :       "  this.message = msg;                               "
    5868             :       "}                                                   "
    5869             :       "MyError.prototype = new Error();                    "
    5870             :       "throw new MyError('my message');                    ");
    5871             : 
    5872             :   // Closure.
    5873             :   CompileRun(
    5874             :       "function MyError(msg) {                             "
    5875             :       "  this.name = 'MyError';                            "
    5876             :       "  this.message = msg;                               "
    5877             :       "}                                                   "
    5878             :       "inherits = function(childCtor, parentCtor) {        "
    5879             :       "    function tempCtor() {};                         "
    5880             :       "    tempCtor.prototype = parentCtor.prototype;      "
    5881             :       "    childCtor.superClass_ = parentCtor.prototype;   "
    5882             :       "    childCtor.prototype = new tempCtor();           "
    5883             :       "    childCtor.prototype.constructor = childCtor;    "
    5884             :       "};                                                  "
    5885             :       "inherits(MyError, Error);                           "
    5886             :       "throw new MyError('my message');                    ");
    5887             : 
    5888             :   // Object.create.
    5889             :   CompileRun(
    5890             :       "function MyError(msg) {                             "
    5891             :       "  this.name = 'MyError';                            "
    5892             :       "  this.message = msg;                               "
    5893             :       "}                                                   "
    5894             :       "MyError.prototype = Object.create(Error.prototype); "
    5895             :       "throw new MyError('my message');                    ");
    5896             : 
    5897          10 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
    5898           5 : }
    5899             : 
    5900             : 
    5901          10 : static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
    5902             :                                             v8::Local<v8::Value> data) {
    5903          10 :   CHECK(data->IsExternal());
    5904          10 :   int* callcount = static_cast<int*>(data.As<v8::External>()->Value());
    5905          10 :   ++*callcount;
    5906             : 
    5907             :   const char* uncaught_error = "Uncaught exception";
    5908          50 :   CHECK(message->Get()
    5909             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5910             :                      v8_str(uncaught_error))
    5911             :             .FromJust());
    5912             :   // Test that compiling code inside a message handler works.
    5913          40 :   CHECK(CompileRunChecked(CcTest::isolate(), "(function(a) { return a; })(42)")
    5914             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5915             :                      v8::Integer::NewFromUnsigned(CcTest::isolate(), 42))
    5916             :             .FromJust());
    5917          10 : }
    5918             : 
    5919             : 
    5920       28342 : TEST(CustomErrorRethrowsOnToString) {
    5921           5 :   int callcount = 0;
    5922           5 :   LocalContext context;
    5923           5 :   v8::Isolate* isolate = context->GetIsolate();
    5924          10 :   v8::HandleScope scope(isolate);
    5925             :   context->GetIsolate()->AddMessageListener(
    5926          10 :       check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
    5927             : 
    5928             :   CompileRun(
    5929             :       "var e = { toString: function() { throw e; } };"
    5930             :       "try { throw e; } finally {}");
    5931             : 
    5932           5 :   CHECK_EQ(callcount, 1);
    5933             :   context->GetIsolate()->RemoveMessageListeners(
    5934          10 :       check_custom_rethrowing_message);
    5935           5 : }
    5936             : 
    5937       28342 : TEST(CustomErrorRethrowsOnToStringInsideVerboseTryCatch) {
    5938           5 :   int callcount = 0;
    5939           5 :   LocalContext context;
    5940           5 :   v8::Isolate* isolate = context->GetIsolate();
    5941          10 :   v8::HandleScope scope(isolate);
    5942          10 :   v8::TryCatch try_catch(isolate);
    5943           5 :   try_catch.SetVerbose(true);
    5944             :   context->GetIsolate()->AddMessageListener(
    5945          10 :       check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
    5946             : 
    5947             :   CompileRun(
    5948             :       "var e = { toString: function() { throw e; } };"
    5949             :       "try { throw e; } finally {}");
    5950             : 
    5951           5 :   CHECK_EQ(callcount, 1);
    5952             :   context->GetIsolate()->RemoveMessageListeners(
    5953          10 :       check_custom_rethrowing_message);
    5954           5 : }
    5955             : 
    5956             : 
    5957          15 : static void receive_message(v8::Local<v8::Message> message,
    5958             :                             v8::Local<v8::Value> data) {
    5959          15 :   message->Get();
    5960          15 :   message_received = true;
    5961          15 : }
    5962             : 
    5963             : 
    5964       28342 : TEST(APIThrowMessage) {
    5965           5 :   message_received = false;
    5966           5 :   v8::Isolate* isolate = CcTest::isolate();
    5967           5 :   v8::HandleScope scope(isolate);
    5968           5 :   isolate->AddMessageListener(receive_message);
    5969           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5970             :   templ->Set(v8_str("ThrowFromC"),
    5971          15 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5972          10 :   LocalContext context(nullptr, templ);
    5973             :   CompileRun("ThrowFromC();");
    5974           5 :   CHECK(message_received);
    5975          10 :   isolate->RemoveMessageListeners(receive_message);
    5976           5 : }
    5977             : 
    5978             : 
    5979       28342 : TEST(APIThrowMessageAndVerboseTryCatch) {
    5980           5 :   message_received = false;
    5981           5 :   v8::Isolate* isolate = CcTest::isolate();
    5982           5 :   v8::HandleScope scope(isolate);
    5983           5 :   isolate->AddMessageListener(receive_message);
    5984           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5985             :   templ->Set(v8_str("ThrowFromC"),
    5986          15 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5987          10 :   LocalContext context(nullptr, templ);
    5988          10 :   v8::TryCatch try_catch(isolate);
    5989           5 :   try_catch.SetVerbose(true);
    5990             :   Local<Value> result = CompileRun("ThrowFromC();");
    5991           5 :   CHECK(try_catch.HasCaught());
    5992           5 :   CHECK(result.IsEmpty());
    5993           5 :   CHECK(message_received);
    5994          10 :   isolate->RemoveMessageListeners(receive_message);
    5995           5 : }
    5996             : 
    5997             : 
    5998       28342 : TEST(APIStackOverflowAndVerboseTryCatch) {
    5999           5 :   message_received = false;
    6000           5 :   LocalContext context;
    6001          10 :   v8::HandleScope scope(context->GetIsolate());
    6002           5 :   context->GetIsolate()->AddMessageListener(receive_message);
    6003          10 :   v8::TryCatch try_catch(context->GetIsolate());
    6004           5 :   try_catch.SetVerbose(true);
    6005             :   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
    6006           5 :   CHECK(try_catch.HasCaught());
    6007           5 :   CHECK(result.IsEmpty());
    6008           5 :   CHECK(message_received);
    6009          10 :   context->GetIsolate()->RemoveMessageListeners(receive_message);
    6010           5 : }
    6011             : 
    6012             : 
    6013       28343 : THREADED_TEST(ExternalScriptException) {
    6014           6 :   v8::Isolate* isolate = CcTest::isolate();
    6015           6 :   v8::HandleScope scope(isolate);
    6016           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6017             :   templ->Set(v8_str("ThrowFromC"),
    6018          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    6019          12 :   LocalContext context(nullptr, templ);
    6020             : 
    6021          12 :   v8::TryCatch try_catch(isolate);
    6022             :   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
    6023           6 :   CHECK(result.IsEmpty());
    6024           6 :   CHECK(try_catch.HasCaught());
    6025          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6026          12 :   CHECK_EQ(0, strcmp("konto", *exception_value));
    6027           6 : }
    6028             : 
    6029             : 
    6030         370 : void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6031          85 :   ApiTestFuzzer::Fuzz();
    6032          85 :   CHECK_EQ(4, args.Length());
    6033          85 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    6034         170 :   int count = args[0]->Int32Value(context).FromJust();
    6035         170 :   int cInterval = args[2]->Int32Value(context).FromJust();
    6036          85 :   if (count == 0) {
    6037          10 :     args.GetIsolate()->ThrowException(v8_str("FromC"));
    6038           5 :     return;
    6039             :   } else {
    6040          80 :     Local<v8::Object> global = context->Global();
    6041             :     Local<Value> fun =
    6042         240 :         global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
    6043         320 :     v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
    6044          80 :     if (count % cInterval == 0) {
    6045          30 :       v8::TryCatch try_catch(args.GetIsolate());
    6046             :       Local<Value> result = fun.As<Function>()
    6047          30 :                                 ->Call(context, global, 4, argv)
    6048          60 :                                 .FromMaybe(Local<Value>());
    6049          60 :       int expected = args[3]->Int32Value(context).FromJust();
    6050          30 :       if (try_catch.HasCaught()) {
    6051          15 :         CHECK_EQ(expected, count);
    6052          15 :         CHECK(result.IsEmpty());
    6053          15 :         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
    6054             :       } else {
    6055          15 :         CHECK_NE(expected, count);
    6056             :       }
    6057             :       args.GetReturnValue().Set(result);
    6058          30 :       return;
    6059             :     } else {
    6060             :       args.GetReturnValue().Set(fun.As<Function>()
    6061          50 :                                     ->Call(context, global, 4, argv)
    6062         100 :                                     .FromMaybe(v8::Local<v8::Value>()));
    6063          50 :       return;
    6064             :     }
    6065             :   }
    6066             : }
    6067             : 
    6068             : 
    6069          75 : void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6070          25 :   ApiTestFuzzer::Fuzz();
    6071          25 :   CHECK_EQ(3, args.Length());
    6072             :   v8::Isolate* isolate = args.GetIsolate();
    6073          25 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
    6074          25 :   bool equality = args[0]->BooleanValue(isolate);
    6075          50 :   int count = args[1]->Int32Value(context).FromJust();
    6076          50 :   int expected = args[2]->Int32Value(context).FromJust();
    6077          25 :   if (equality) {
    6078          15 :     CHECK_EQ(count, expected);
    6079             :   } else {
    6080          10 :     CHECK_NE(count, expected);
    6081             :   }
    6082          25 : }
    6083             : 
    6084             : 
    6085       28343 : THREADED_TEST(EvalInTryFinally) {
    6086           6 :   LocalContext context;
    6087          12 :   v8::HandleScope scope(context->GetIsolate());
    6088          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6089             :   CompileRun(
    6090             :       "(function() {"
    6091             :       "  try {"
    6092             :       "    eval('asldkf (*&^&*^');"
    6093             :       "  } finally {"
    6094             :       "    return;"
    6095             :       "  }"
    6096             :       "})()");
    6097          12 :   CHECK(!try_catch.HasCaught());
    6098           6 : }
    6099             : 
    6100             : 
    6101             : // This test works by making a stack of alternating JavaScript and C
    6102             : // activations.  These activations set up exception handlers with regular
    6103             : // intervals, one interval for C activations and another for JavaScript
    6104             : // activations.  When enough activations have been created an exception is
    6105             : // thrown and we check that the right activation catches the exception and that
    6106             : // no other activations do.  The right activation is always the topmost one with
    6107             : // a handler, regardless of whether it is in JavaScript or C.
    6108             : //
    6109             : // The notation used to describe a test case looks like this:
    6110             : //
    6111             : //    *JS[4] *C[3] @JS[2] C[1] JS[0]
    6112             : //
    6113             : // Each entry is an activation, either JS or C.  The index is the count at that
    6114             : // level.  Stars identify activations with exception handlers, the @ identifies
    6115             : // the exception handler that should catch the exception.
    6116             : //
    6117             : // BUG(271): Some of the exception propagation does not work on the
    6118             : // ARM simulator because the simulator separates the C++ stack and the
    6119             : // JS stack.  This test therefore fails on the simulator.  The test is
    6120             : // not threaded to allow the threading tests to run on the simulator.
    6121       28342 : TEST(ExceptionOrder) {
    6122           5 :   v8::Isolate* isolate = CcTest::isolate();
    6123           5 :   v8::HandleScope scope(isolate);
    6124           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6125          15 :   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
    6126             :   templ->Set(v8_str("CThrowCountDown"),
    6127          15 :              v8::FunctionTemplate::New(isolate, CThrowCountDown));
    6128          10 :   LocalContext context(nullptr, templ);
    6129             :   CompileRun(
    6130             :       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
    6131             :       "  if (count == 0) throw 'FromJS';"
    6132             :       "  if (count % jsInterval == 0) {"
    6133             :       "    try {"
    6134             :       "      var value = CThrowCountDown(count - 1,"
    6135             :       "                                  jsInterval,"
    6136             :       "                                  cInterval,"
    6137             :       "                                  expected);"
    6138             :       "      check(false, count, expected);"
    6139             :       "      return value;"
    6140             :       "    } catch (e) {"
    6141             :       "      check(true, count, expected);"
    6142             :       "    }"
    6143             :       "  } else {"
    6144             :       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
    6145             :       "  }"
    6146             :       "}");
    6147             :   Local<Function> fun = Local<Function>::Cast(
    6148             :       context->Global()
    6149          20 :           ->Get(context.local(), v8_str("JSThrowCountDown"))
    6150           5 :           .ToLocalChecked());
    6151             : 
    6152             :   const int argc = 4;
    6153             :   //                             count      jsInterval cInterval  expected
    6154             : 
    6155             :   // *JS[4] *C[3] @JS[2] C[1] JS[0]
    6156           5 :   v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
    6157          10 :   fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
    6158             : 
    6159             :   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
    6160           5 :   v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
    6161          10 :   fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
    6162             : 
    6163             :   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6164           5 :   v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
    6165          10 :   fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
    6166             : 
    6167             :   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6168           5 :   v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
    6169          10 :   fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
    6170             : 
    6171             :   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
    6172           5 :   v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
    6173          10 :   fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
    6174             : 
    6175             :   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
    6176           5 :   v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
    6177          15 :   fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
    6178           5 : }
    6179             : 
    6180             : 
    6181         126 : void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6182          42 :   ApiTestFuzzer::Fuzz();
    6183          42 :   CHECK_EQ(1, args.Length());
    6184          42 :   args.GetIsolate()->ThrowException(args[0]);
    6185          42 : }
    6186             : 
    6187             : 
    6188       28343 : THREADED_TEST(ThrowValues) {
    6189           6 :   v8::Isolate* isolate = CcTest::isolate();
    6190           6 :   v8::HandleScope scope(isolate);
    6191           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6192          18 :   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
    6193          12 :   LocalContext context(nullptr, templ);
    6194             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
    6195             :       CompileRun("function Run(obj) {"
    6196             :                  "  try {"
    6197             :                  "    Throw(obj);"
    6198             :                  "  } catch (e) {"
    6199             :                  "    return e;"
    6200             :                  "  }"
    6201             :                  "  return 'no exception';"
    6202             :                  "}"
    6203             :                  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
    6204           6 :   CHECK_EQ(5u, result->Length());
    6205          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
    6206             :             .ToLocalChecked()
    6207             :             ->IsString());
    6208          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
    6209             :             .ToLocalChecked()
    6210             :             ->IsNumber());
    6211          24 :   CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
    6212             :                   .ToLocalChecked()
    6213             :                   ->Int32Value(context.local())
    6214             :                   .FromJust());
    6215          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
    6216             :             .ToLocalChecked()
    6217             :             ->IsNumber());
    6218          24 :   CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
    6219             :                   .ToLocalChecked()
    6220             :                   ->Int32Value(context.local())
    6221             :                   .FromJust());
    6222          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
    6223             :             .ToLocalChecked()
    6224             :             ->IsNull());
    6225          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
    6226             :             .ToLocalChecked()
    6227           6 :             ->IsUndefined());
    6228           6 : }
    6229             : 
    6230             : 
    6231       28343 : THREADED_TEST(CatchZero) {
    6232           6 :   LocalContext context;
    6233          12 :   v8::HandleScope scope(context->GetIsolate());
    6234          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6235           6 :   CHECK(!try_catch.HasCaught());
    6236             :   CompileRun("throw 10");
    6237           6 :   CHECK(try_catch.HasCaught());
    6238          18 :   CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6239           6 :   try_catch.Reset();
    6240           6 :   CHECK(!try_catch.HasCaught());
    6241             :   CompileRun("throw 0");
    6242           6 :   CHECK(try_catch.HasCaught());
    6243          24 :   CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6244           6 : }
    6245             : 
    6246             : 
    6247       28343 : THREADED_TEST(CatchExceptionFromWith) {
    6248           6 :   LocalContext context;
    6249          12 :   v8::HandleScope scope(context->GetIsolate());
    6250          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6251           6 :   CHECK(!try_catch.HasCaught());
    6252             :   CompileRun("var o = {}; with (o) { throw 42; }");
    6253          12 :   CHECK(try_catch.HasCaught());
    6254           6 : }
    6255             : 
    6256             : 
    6257       28343 : THREADED_TEST(TryCatchAndFinallyHidingException) {
    6258           6 :   LocalContext context;
    6259          12 :   v8::HandleScope scope(context->GetIsolate());
    6260          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6261           6 :   CHECK(!try_catch.HasCaught());
    6262             :   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
    6263             :   CompileRun("f({toString: function() { throw 42; }});");
    6264          12 :   CHECK(!try_catch.HasCaught());
    6265           6 : }
    6266             : 
    6267             : 
    6268           6 : void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6269           6 :   v8::TryCatch try_catch(args.GetIsolate());
    6270           6 : }
    6271             : 
    6272             : 
    6273       28343 : THREADED_TEST(TryCatchAndFinally) {
    6274           6 :   LocalContext context;
    6275           6 :   v8::Isolate* isolate = context->GetIsolate();
    6276          12 :   v8::HandleScope scope(isolate);
    6277          48 :   CHECK(context->Global()
    6278             :             ->Set(context.local(), v8_str("native_with_try_catch"),
    6279             :                   v8::FunctionTemplate::New(isolate, WithTryCatch)
    6280             :                       ->GetFunction(context.local())
    6281             :                       .ToLocalChecked())
    6282             :             .FromJust());
    6283          12 :   v8::TryCatch try_catch(isolate);
    6284           6 :   CHECK(!try_catch.HasCaught());
    6285             :   CompileRun(
    6286             :       "try {\n"
    6287             :       "  throw new Error('a');\n"
    6288             :       "} finally {\n"
    6289             :       "  native_with_try_catch();\n"
    6290             :       "}\n");
    6291          12 :   CHECK(try_catch.HasCaught());
    6292           6 : }
    6293             : 
    6294             : 
    6295          30 : static void TryCatchNested1Helper(int depth) {
    6296          30 :   if (depth > 0) {
    6297          25 :     v8::TryCatch try_catch(CcTest::isolate());
    6298          25 :     try_catch.SetVerbose(true);
    6299          25 :     TryCatchNested1Helper(depth - 1);
    6300          25 :     CHECK(try_catch.HasCaught());
    6301          25 :     try_catch.ReThrow();
    6302             :   } else {
    6303          10 :     CcTest::isolate()->ThrowException(v8_str("E1"));
    6304             :   }
    6305          30 : }
    6306             : 
    6307             : 
    6308          30 : static void TryCatchNested2Helper(int depth) {
    6309          30 :   if (depth > 0) {
    6310          25 :     v8::TryCatch try_catch(CcTest::isolate());
    6311          25 :     try_catch.SetVerbose(true);
    6312          25 :     TryCatchNested2Helper(depth - 1);
    6313          25 :     CHECK(try_catch.HasCaught());
    6314          25 :     try_catch.ReThrow();
    6315             :   } else {
    6316             :     CompileRun("throw 'E2';");
    6317             :   }
    6318          30 : }
    6319             : 
    6320             : 
    6321       28342 : TEST(TryCatchNested) {
    6322           5 :   v8::V8::Initialize();
    6323           5 :   LocalContext context;
    6324          10 :   v8::HandleScope scope(context->GetIsolate());
    6325             : 
    6326             :   {
    6327             :     // Test nested try-catch with a native throw in the end.
    6328           5 :     v8::TryCatch try_catch(context->GetIsolate());
    6329           5 :     TryCatchNested1Helper(5);
    6330           5 :     CHECK(try_catch.HasCaught());
    6331          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6332             :                                               try_catch.Exception()),
    6333           5 :                        "E1"));
    6334             :   }
    6335             : 
    6336             :   {
    6337             :     // Test nested try-catch with a JavaScript throw in the end.
    6338           5 :     v8::TryCatch try_catch(context->GetIsolate());
    6339           5 :     TryCatchNested2Helper(5);
    6340           5 :     CHECK(try_catch.HasCaught());
    6341          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6342             :                                               try_catch.Exception()),
    6343           5 :                        "E2"));
    6344           5 :   }
    6345           5 : }
    6346             : 
    6347             : 
    6348          10 : void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
    6349          10 :   CHECK(try_catch->HasCaught());
    6350          10 :   Local<Message> message = try_catch->Message();
    6351          10 :   Local<Value> resource = message->GetScriptOrigin().ResourceName();
    6352          10 :   CHECK_EQ(
    6353             :       0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), resource), "inner"));
    6354          20 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), message->Get()),
    6355             :                      "Uncaught Error: a"));
    6356          20 :   CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
    6357             :                   .FromJust());
    6358          20 :   CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
    6359             :                   .FromJust());
    6360          10 : }
    6361             : 
    6362             : 
    6363           5 : void TryCatchMixedNestingHelper(
    6364           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6365           5 :   ApiTestFuzzer::Fuzz();
    6366           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6367           5 :   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
    6368           5 :   CHECK(try_catch.HasCaught());
    6369           5 :   TryCatchMixedNestingCheck(&try_catch);
    6370           5 :   try_catch.ReThrow();
    6371           5 : }
    6372             : 
    6373             : 
    6374             : // This test ensures that an outer TryCatch in the following situation:
    6375             : //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
    6376             : // does not clobber the Message object generated for the inner TryCatch.
    6377             : // This exercises the ability of TryCatch.ReThrow() to restore the
    6378             : // inner pending Message before throwing the exception again.
    6379       28342 : TEST(TryCatchMixedNesting) {
    6380           5 :   v8::Isolate* isolate = CcTest::isolate();
    6381           5 :   v8::HandleScope scope(isolate);
    6382           5 :   v8::V8::Initialize();
    6383          10 :   v8::TryCatch try_catch(isolate);
    6384           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6385             :   templ->Set(v8_str("TryCatchMixedNestingHelper"),
    6386          15 :              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
    6387          10 :   LocalContext context(nullptr, templ);
    6388           5 :   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
    6389          10 :   TryCatchMixedNestingCheck(&try_catch);
    6390           5 : }
    6391             : 
    6392             : 
    6393          15 : void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6394           5 :   ApiTestFuzzer::Fuzz();
    6395           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6396          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6397           5 :   CHECK(try_catch.HasCaught());
    6398           5 : }
    6399             : 
    6400             : 
    6401       28342 : TEST(TryCatchNative) {
    6402           5 :   v8::Isolate* isolate = CcTest::isolate();
    6403           5 :   v8::HandleScope scope(isolate);
    6404           5 :   v8::V8::Initialize();
    6405          10 :   v8::TryCatch try_catch(isolate);
    6406           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6407             :   templ->Set(v8_str("TryCatchNativeHelper"),
    6408          15 :              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
    6409          10 :   LocalContext context(nullptr, templ);
    6410             :   CompileRun("TryCatchNativeHelper();");
    6411          10 :   CHECK(!try_catch.HasCaught());
    6412           5 : }
    6413             : 
    6414             : 
    6415           5 : void TryCatchNativeResetHelper(
    6416          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6417           5 :   ApiTestFuzzer::Fuzz();
    6418           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6419          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6420           5 :   CHECK(try_catch.HasCaught());
    6421           5 :   try_catch.Reset();
    6422           5 :   CHECK(!try_catch.HasCaught());
    6423           5 : }
    6424             : 
    6425             : 
    6426       28342 : TEST(TryCatchNativeReset) {
    6427           5 :   v8::Isolate* isolate = CcTest::isolate();
    6428           5 :   v8::HandleScope scope(isolate);
    6429           5 :   v8::V8::Initialize();
    6430          10 :   v8::TryCatch try_catch(isolate);
    6431           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6432             :   templ->Set(v8_str("TryCatchNativeResetHelper"),
    6433          15 :              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
    6434          10 :   LocalContext context(nullptr, templ);
    6435             :   CompileRun("TryCatchNativeResetHelper();");
    6436          10 :   CHECK(!try_catch.HasCaught());
    6437           5 : }
    6438             : 
    6439             : 
    6440       28343 : THREADED_TEST(Equality) {
    6441           6 :   LocalContext context;
    6442           6 :   v8::Isolate* isolate = context->GetIsolate();
    6443          12 :   v8::HandleScope scope(context->GetIsolate());
    6444             :   // Check that equality works at all before relying on CHECK_EQ
    6445          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6446          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6447             : 
    6448          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6449          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6450          18 :   CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
    6451          18 :   CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
    6452          18 :   CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
    6453             : 
    6454             :   // Assume String is not internalized.
    6455          18 :   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
    6456          18 :   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
    6457          12 :   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
    6458          12 :   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
    6459          12 :   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
    6460          12 :   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
    6461           6 :   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
    6462           6 :   CHECK(!not_a_number->StrictEquals(not_a_number));
    6463           6 :   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
    6464           6 :   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
    6465             : 
    6466           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    6467             :   v8::Persistent<v8::Object> alias(isolate, obj);
    6468           6 :   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
    6469             :   alias.Reset();
    6470             : 
    6471          18 :   CHECK(v8_str("a")->SameValue(v8_str("a")));
    6472          18 :   CHECK(!v8_str("a")->SameValue(v8_str("b")));
    6473          12 :   CHECK(!v8_str("5")->SameValue(v8_num(5)));
    6474          12 :   CHECK(v8_num(1)->SameValue(v8_num(1)));
    6475          12 :   CHECK(!v8_num(1)->SameValue(v8_num(2)));
    6476          12 :   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
    6477           6 :   CHECK(not_a_number->SameValue(not_a_number));
    6478           6 :   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
    6479          12 :   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
    6480           6 : }
    6481             : 
    6482       28343 : THREADED_TEST(TypeOf) {
    6483           6 :   LocalContext context;
    6484           6 :   v8::Isolate* isolate = context->GetIsolate();
    6485          12 :   v8::HandleScope scope(context->GetIsolate());
    6486             : 
    6487           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
    6488          12 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
    6489             : 
    6490          30 :   CHECK(v8::Undefined(isolate)
    6491             :             ->TypeOf(isolate)
    6492             :             ->Equals(context.local(), v8_str("undefined"))
    6493             :             .FromJust());
    6494          30 :   CHECK(v8::Null(isolate)
    6495             :             ->TypeOf(isolate)
    6496             :             ->Equals(context.local(), v8_str("object"))
    6497             :             .FromJust());
    6498          30 :   CHECK(v8_str("str")
    6499             :             ->TypeOf(isolate)
    6500             :             ->Equals(context.local(), v8_str("string"))
    6501             :             .FromJust());
    6502          30 :   CHECK(v8_num(0.0)
    6503             :             ->TypeOf(isolate)
    6504             :             ->Equals(context.local(), v8_str("number"))
    6505             :             .FromJust());
    6506          30 :   CHECK(v8_num(1)
    6507             :             ->TypeOf(isolate)
    6508             :             ->Equals(context.local(), v8_str("number"))
    6509             :             .FromJust());
    6510          30 :   CHECK(v8::Object::New(isolate)
    6511             :             ->TypeOf(isolate)
    6512             :             ->Equals(context.local(), v8_str("object"))
    6513             :             .FromJust());
    6514          30 :   CHECK(v8::Boolean::New(isolate, true)
    6515             :             ->TypeOf(isolate)
    6516             :             ->Equals(context.local(), v8_str("boolean"))
    6517             :             .FromJust());
    6518          24 :   CHECK(fun->TypeOf(isolate)
    6519             :             ->Equals(context.local(), v8_str("function"))
    6520           6 :             .FromJust());
    6521           6 : }
    6522             : 
    6523       28343 : THREADED_TEST(InstanceOf) {
    6524           6 :   LocalContext env;
    6525          12 :   v8::HandleScope scope(env->GetIsolate());
    6526             :   CompileRun(
    6527             :       "var A = {};"
    6528             :       "var B = {};"
    6529             :       "var C = {};"
    6530             :       "B.__proto__ = A;"
    6531             :       "C.__proto__ = B;"
    6532             :       "function F() {}"
    6533             :       "F.prototype = A;"
    6534             :       "var G = { [Symbol.hasInstance] : null};"
    6535             :       "var H = { [Symbol.hasInstance] : () => { throw new Error(); } };"
    6536             :       "var J = { [Symbol.hasInstance] : () => true };"
    6537             :       "class K {}"
    6538             :       "var D = new K;"
    6539             :       "class L extends K {}"
    6540             :       "var E = new L");
    6541             : 
    6542           6 :   v8::Local<v8::Object> f = v8::Local<v8::Object>::Cast(CompileRun("F"));
    6543           6 :   v8::Local<v8::Object> g = v8::Local<v8::Object>::Cast(CompileRun("G"));
    6544           6 :   v8::Local<v8::Object> h = v8::Local<v8::Object>::Cast(CompileRun("H"));
    6545           6 :   v8::Local<v8::Object> j = v8::Local<v8::Object>::Cast(CompileRun("J"));
    6546           6 :   v8::Local<v8::Object> k = v8::Local<v8::Object>::Cast(CompileRun("K"));
    6547           6 :   v8::Local<v8::Object> l = v8::Local<v8::Object>::Cast(CompileRun("L"));
    6548             :   v8::Local<v8::Value> a = v8::Local<v8::Value>::Cast(CompileRun("A"));
    6549             :   v8::Local<v8::Value> b = v8::Local<v8::Value>::Cast(CompileRun("B"));
    6550             :   v8::Local<v8::Value> c = v8::Local<v8::Value>::Cast(CompileRun("C"));
    6551             :   v8::Local<v8::Value> d = v8::Local<v8::Value>::Cast(CompileRun("D"));
    6552             :   v8::Local<v8::Value> e = v8::Local<v8::Value>::Cast(CompileRun("E"));
    6553             : 
    6554          12 :   v8::TryCatch try_catch(env->GetIsolate());
    6555          12 :   CHECK(!a->InstanceOf(env.local(), f).ToChecked());
    6556          12 :   CHECK(b->InstanceOf(env.local(), f).ToChecked());
    6557          12 :   CHECK(c->InstanceOf(env.local(), f).ToChecked());
    6558          12 :   CHECK(!d->InstanceOf(env.local(), f).ToChecked());
    6559          12 :   CHECK(!e->InstanceOf(env.local(), f).ToChecked());
    6560           6 :   CHECK(!try_catch.HasCaught());
    6561             : 
    6562          12 :   CHECK(a->InstanceOf(env.local(), g).IsNothing());
    6563           6 :   CHECK(try_catch.HasCaught());
    6564           6 :   try_catch.Reset();
    6565             : 
    6566          12 :   CHECK(b->InstanceOf(env.local(), h).IsNothing());
    6567           6 :   CHECK(try_catch.HasCaught());
    6568           6 :   try_catch.Reset();
    6569             : 
    6570          18 :   CHECK(v8_num(1)->InstanceOf(env.local(), j).ToChecked());
    6571           6 :   CHECK(!try_catch.HasCaught());
    6572             : 
    6573          12 :   CHECK(d->InstanceOf(env.local(), k).ToChecked());
    6574          12 :   CHECK(e->InstanceOf(env.local(), k).ToChecked());
    6575          12 :   CHECK(!d->InstanceOf(env.local(), l).ToChecked());
    6576          12 :   CHECK(e->InstanceOf(env.local(), l).ToChecked());
    6577          12 :   CHECK(!try_catch.HasCaught());
    6578           6 : }
    6579             : 
    6580       28343 : THREADED_TEST(MultiRun) {
    6581           6 :   LocalContext context;
    6582          12 :   v8::HandleScope scope(context->GetIsolate());
    6583             :   Local<Script> script = v8_compile("x");
    6584          66 :   for (int i = 0; i < 10; i++) {
    6585          60 :     script->Run(context.local()).IsEmpty();
    6586           6 :   }
    6587           6 : }
    6588             : 
    6589             : 
    6590         204 : static void GetXValue(Local<Name> name,
    6591             :                       const v8::PropertyCallbackInfo<v8::Value>& info) {
    6592         204 :   ApiTestFuzzer::Fuzz();
    6593         816 :   CHECK(info.Data()
    6594             :             ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
    6595             :             .FromJust());
    6596         816 :   CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
    6597             :             .FromJust());
    6598             :   info.GetReturnValue().Set(name);
    6599         204 : }
    6600             : 
    6601             : 
    6602       28343 : THREADED_TEST(SimplePropertyRead) {
    6603           6 :   LocalContext context;
    6604           6 :   v8::Isolate* isolate = context->GetIsolate();
    6605          12 :   v8::HandleScope scope(isolate);
    6606           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6607          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6608          36 :   CHECK(context->Global()
    6609             :             ->Set(context.local(), v8_str("obj"),
    6610             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6611             :             .FromJust());
    6612             :   Local<Script> script = v8_compile("obj.x");
    6613          66 :   for (int i = 0; i < 10; i++) {
    6614          60 :     Local<Value> result = script->Run(context.local()).ToLocalChecked();
    6615         180 :     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    6616           6 :   }
    6617           6 : }
    6618             : 
    6619             : 
    6620       28343 : THREADED_TEST(DefinePropertyOnAPIAccessor) {
    6621           6 :   LocalContext context;
    6622           6 :   v8::Isolate* isolate = context->GetIsolate();
    6623          12 :   v8::HandleScope scope(isolate);
    6624           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6625          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6626          36 :   CHECK(context->Global()
    6627             :             ->Set(context.local(), v8_str("obj"),
    6628             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6629             :             .FromJust());
    6630             : 
    6631             :   // Uses getOwnPropertyDescriptor to check the configurable status
    6632             :   Local<Script> script_desc = v8_compile(
    6633             :       "var prop = Object.getOwnPropertyDescriptor( "
    6634             :       "obj, 'x');"
    6635             :       "prop.configurable;");
    6636           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6637           6 :   CHECK(result->BooleanValue(isolate));
    6638             : 
    6639             :   // Redefine get - but still configurable
    6640             :   Local<Script> script_define = v8_compile(
    6641             :       "var desc = { get: function(){return 42; },"
    6642             :       "            configurable: true };"
    6643             :       "Object.defineProperty(obj, 'x', desc);"
    6644             :       "obj.x");
    6645           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6646          12 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6647             : 
    6648             :   // Check that the accessor is still configurable
    6649           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6650           6 :   CHECK(result->BooleanValue(isolate));
    6651             : 
    6652             :   // Redefine to a non-configurable
    6653             :   script_define = v8_compile(
    6654             :       "var desc = { get: function(){return 43; },"
    6655             :       "             configurable: false };"
    6656             :       "Object.defineProperty(obj, 'x', desc);"
    6657             :       "obj.x");
    6658           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6659          12 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6660           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6661           6 :   CHECK(!result->BooleanValue(isolate));
    6662             : 
    6663             :   // Make sure that it is not possible to redefine again
    6664          12 :   v8::TryCatch try_catch(isolate);
    6665          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6666           6 :   CHECK(try_catch.HasCaught());
    6667          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6668           6 :   CHECK_EQ(0,
    6669           6 :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6670           6 : }
    6671             : 
    6672             : 
    6673       28343 : THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
    6674           6 :   v8::Isolate* isolate = CcTest::isolate();
    6675           6 :   v8::HandleScope scope(isolate);
    6676           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6677          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6678          12 :   LocalContext context;
    6679          36 :   CHECK(context->Global()
    6680             :             ->Set(context.local(), v8_str("obj"),
    6681             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6682             :             .FromJust());
    6683             : 
    6684             :   Local<Script> script_desc = v8_compile(
    6685             :       "var prop ="
    6686             :       "Object.getOwnPropertyDescriptor( "
    6687             :       "obj, 'x');"
    6688             :       "prop.configurable;");
    6689           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6690           6 :   CHECK(result->BooleanValue(isolate));
    6691             : 
    6692             :   Local<Script> script_define = v8_compile(
    6693             :       "var desc = {get: function(){return 42; },"
    6694             :       "            configurable: true };"
    6695             :       "Object.defineProperty(obj, 'x', desc);"
    6696             :       "obj.x");
    6697           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6698          12 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6699             : 
    6700           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6701           6 :   CHECK(result->BooleanValue(isolate));
    6702             : 
    6703             :   script_define = v8_compile(
    6704             :       "var desc = {get: function(){return 43; },"
    6705             :       "            configurable: false };"
    6706             :       "Object.defineProperty(obj, 'x', desc);"
    6707             :       "obj.x");
    6708           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6709          12 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6710             : 
    6711           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6712           6 :   CHECK(!result->BooleanValue(isolate));
    6713             : 
    6714          12 :   v8::TryCatch try_catch(isolate);
    6715          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6716           6 :   CHECK(try_catch.HasCaught());
    6717          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6718           6 :   CHECK_EQ(0,
    6719           6 :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6720           6 : }
    6721             : 
    6722             : 
    6723          72 : static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
    6724             :                                                char const* name) {
    6725             :   return v8::Local<v8::Object>::Cast(
    6726             :       (*context)
    6727             :           ->Global()
    6728         288 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
    6729         144 :           .ToLocalChecked());
    6730             : }
    6731             : 
    6732             : 
    6733       28343 : THREADED_TEST(DefineAPIAccessorOnObject) {
    6734           6 :   v8::Isolate* isolate = CcTest::isolate();
    6735           6 :   v8::HandleScope scope(isolate);
    6736           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6737          12 :   LocalContext context;
    6738             : 
    6739          42 :   CHECK(context->Global()
    6740             :             ->Set(context.local(), v8_str("obj1"),
    6741             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6742             :             .FromJust());
    6743             :   CompileRun("var obj2 = {};");
    6744             : 
    6745           6 :   CHECK(CompileRun("obj1.x")->IsUndefined());
    6746           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6747             : 
    6748          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6749             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6750             :                           v8_str("donut"))
    6751             :             .FromJust());
    6752             : 
    6753           6 :   ExpectString("obj1.x", "x");
    6754           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6755             : 
    6756          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6757             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6758             :                           v8_str("donut"))
    6759             :             .FromJust());
    6760             : 
    6761           6 :   ExpectString("obj1.x", "x");
    6762           6 :   ExpectString("obj2.x", "x");
    6763             : 
    6764             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6765             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6766             : 
    6767             :   CompileRun(
    6768             :       "Object.defineProperty(obj1, 'x',"
    6769             :       "{ get: function() { return 'y'; }, configurable: true })");
    6770             : 
    6771           6 :   ExpectString("obj1.x", "y");
    6772           6 :   ExpectString("obj2.x", "x");
    6773             : 
    6774             :   CompileRun(
    6775             :       "Object.defineProperty(obj2, 'x',"
    6776             :       "{ get: function() { return 'y'; }, configurable: true })");
    6777             : 
    6778           6 :   ExpectString("obj1.x", "y");
    6779           6 :   ExpectString("obj2.x", "y");
    6780             : 
    6781             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6782             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6783             : 
    6784          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6785             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6786             :                           v8_str("donut"))
    6787             :             .FromJust());
    6788          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6789             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6790             :                           v8_str("donut"))
    6791             :             .FromJust());
    6792             : 
    6793           6 :   ExpectString("obj1.x", "x");
    6794           6 :   ExpectString("obj2.x", "x");
    6795             : 
    6796             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6797             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6798             : 
    6799             :   // Define getters/setters, but now make them not configurable.
    6800             :   CompileRun(
    6801             :       "Object.defineProperty(obj1, 'x',"
    6802             :       "{ get: function() { return 'z'; }, configurable: false })");
    6803             :   CompileRun(
    6804             :       "Object.defineProperty(obj2, 'x',"
    6805             :       "{ get: function() { return 'z'; }, configurable: false })");
    6806             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6807             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6808             : 
    6809           6 :   ExpectString("obj1.x", "z");
    6810           6 :   ExpectString("obj2.x", "z");
    6811             : 
    6812          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6813             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6814             :                            v8_str("donut"))
    6815             :              .FromJust());
    6816          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6817             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6818             :                            v8_str("donut"))
    6819             :              .FromJust());
    6820             : 
    6821           6 :   ExpectString("obj1.x", "z");
    6822          12 :   ExpectString("obj2.x", "z");
    6823           6 : }
    6824             : 
    6825             : 
    6826       28343 : THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
    6827           6 :   v8::Isolate* isolate = CcTest::isolate();
    6828           6 :   v8::HandleScope scope(isolate);
    6829           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6830          12 :   LocalContext context;
    6831             : 
    6832          42 :   CHECK(context->Global()
    6833             :             ->Set(context.local(), v8_str("obj1"),
    6834             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6835             :             .FromJust());
    6836             :   CompileRun("var obj2 = {};");
    6837             : 
    6838          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6839             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6840             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6841             :             .FromJust());
    6842          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6843             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6844             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6845             :             .FromJust());
    6846             : 
    6847           6 :   ExpectString("obj1.x", "x");
    6848           6 :   ExpectString("obj2.x", "x");
    6849             : 
    6850             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6851             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6852             : 
    6853          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6854             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6855             :                            v8_str("donut"))
    6856             :              .FromJust());
    6857          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6858             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6859             :                            v8_str("donut"))
    6860             :              .FromJust());
    6861             : 
    6862             :   {
    6863           6 :     v8::TryCatch try_catch(isolate);
    6864             :     CompileRun(
    6865             :         "Object.defineProperty(obj1, 'x',"
    6866             :         "{get: function() { return 'func'; }})");
    6867           6 :     CHECK(try_catch.HasCaught());
    6868          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6869           6 :     CHECK_EQ(
    6870           6 :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6871             :   }
    6872             :   {
    6873           6 :     v8::TryCatch try_catch(isolate);
    6874             :     CompileRun(
    6875             :         "Object.defineProperty(obj2, 'x',"
    6876             :         "{get: function() { return 'func'; }})");
    6877           6 :     CHECK(try_catch.HasCaught());
    6878          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6879           6 :     CHECK_EQ(
    6880           6 :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6881           6 :   }
    6882           6 : }
    6883             : 
    6884             : 
    6885          24 : static void Get239Value(Local<Name> name,
    6886             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    6887          24 :   ApiTestFuzzer::Fuzz();
    6888          96 :   CHECK(info.Data()
    6889             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
    6890             :             .FromJust());
    6891          96 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
    6892             :             .FromJust());
    6893             :   info.GetReturnValue().Set(name);
    6894          24 : }
    6895             : 
    6896             : 
    6897       28343 : THREADED_TEST(ElementAPIAccessor) {
    6898           6 :   v8::Isolate* isolate = CcTest::isolate();
    6899           6 :   v8::HandleScope scope(isolate);
    6900           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6901          12 :   LocalContext context;
    6902             : 
    6903          42 :   CHECK(context->Global()
    6904             :             ->Set(context.local(), v8_str("obj1"),
    6905             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6906             :             .FromJust());
    6907             :   CompileRun("var obj2 = {};");
    6908             : 
    6909          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6910             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6911             :                           v8_str("donut"))
    6912             :             .FromJust());
    6913          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6914             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6915             :                           v8_str("donut"))
    6916             :             .FromJust());
    6917             : 
    6918           6 :   ExpectString("obj1[239]", "239");
    6919           6 :   ExpectString("obj2[239]", "239");
    6920           6 :   ExpectString("obj1['239']", "239");
    6921          12 :   ExpectString("obj2['239']", "239");
    6922           6 : }
    6923             : 
    6924             : 
    6925       28337 : v8::Persistent<Value> xValue;
    6926             : 
    6927             : 
    6928         120 : static void SetXValue(Local<Name> name, Local<Value> value,
    6929             :                       const v8::PropertyCallbackInfo<void>& info) {
    6930         120 :   Local<Context> context = info.GetIsolate()->GetCurrentContext();
    6931         240 :   CHECK(value->Equals(context, v8_num(4)).FromJust());
    6932         360 :   CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
    6933         360 :   CHECK(name->Equals(context, v8_str("x")).FromJust());
    6934         120 :   CHECK(xValue.IsEmpty());
    6935             :   xValue.Reset(info.GetIsolate(), value);
    6936         120 : }
    6937             : 
    6938             : 
    6939       28343 : THREADED_TEST(SimplePropertyWrite) {
    6940           6 :   v8::Isolate* isolate = CcTest::isolate();
    6941           6 :   v8::HandleScope scope(isolate);
    6942           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6943          18 :   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
    6944          12 :   LocalContext context;
    6945          36 :   CHECK(context->Global()
    6946             :             ->Set(context.local(), v8_str("obj"),
    6947             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6948             :             .FromJust());
    6949             :   Local<Script> script = v8_compile("obj.x = 4");
    6950          66 :   for (int i = 0; i < 10; i++) {
    6951          60 :     CHECK(xValue.IsEmpty());
    6952          60 :     script->Run(context.local()).ToLocalChecked();
    6953         240 :     CHECK(v8_num(4)
    6954             :               ->Equals(context.local(),
    6955             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6956             :               .FromJust());
    6957             :     xValue.Reset();
    6958           6 :   }
    6959           6 : }
    6960             : 
    6961             : 
    6962       28343 : THREADED_TEST(SetterOnly) {
    6963           6 :   v8::Isolate* isolate = CcTest::isolate();
    6964           6 :   v8::HandleScope scope(isolate);
    6965           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6966          18 :   templ->SetAccessor(v8_str("x"), nullptr, SetXValue, v8_str("donut"));
    6967          12 :   LocalContext context;
    6968          36 :   CHECK(context->Global()
    6969             :             ->Set(context.local(), v8_str("obj"),
    6970             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6971             :             .FromJust());
    6972             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    6973          66 :   for (int i = 0; i < 10; i++) {
    6974          60 :     CHECK(xValue.IsEmpty());
    6975          60 :     script->Run(context.local()).ToLocalChecked();
    6976         240 :     CHECK(v8_num(4)
    6977             :               ->Equals(context.local(),
    6978             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6979             :               .FromJust());
    6980             :     xValue.Reset();
    6981           6 :   }
    6982           6 : }
    6983             : 
    6984             : 
    6985       28343 : THREADED_TEST(NoAccessors) {
    6986           6 :   v8::Isolate* isolate = CcTest::isolate();
    6987           6 :   v8::HandleScope scope(isolate);
    6988           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6989             :   templ->SetAccessor(v8_str("x"),
    6990             :                      static_cast<v8::AccessorGetterCallback>(nullptr), nullptr,
    6991          12 :                      v8_str("donut"));
    6992          12 :   LocalContext context;
    6993          36 :   CHECK(context->Global()
    6994             :             ->Set(context.local(), v8_str("obj"),
    6995             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6996             :             .FromJust());
    6997             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    6998          66 :   for (int i = 0; i < 10; i++) {
    6999          60 :     script->Run(context.local()).ToLocalChecked();
    7000           6 :   }
    7001           6 : }
    7002             : 
    7003             : 
    7004       28343 : THREADED_TEST(MultiContexts) {
    7005           6 :   v8::Isolate* isolate = CcTest::isolate();
    7006           6 :   v8::HandleScope scope(isolate);
    7007           6 :   v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7008             :   templ->Set(v8_str("dummy"),
    7009          18 :              v8::FunctionTemplate::New(isolate, DummyCallHandler));
    7010             : 
    7011           6 :   Local<String> password = v8_str("Password");
    7012             : 
    7013             :   // Create an environment
    7014          12 :   LocalContext context0(nullptr, templ);
    7015           6 :   context0->SetSecurityToken(password);
    7016           6 :   v8::Local<v8::Object> global0 = context0->Global();
    7017          18 :   CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
    7018             :             .FromJust());
    7019          24 :   CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
    7020             :                      .ToLocalChecked()
    7021             :                      ->Int32Value(context0.local())
    7022             :                      .FromJust());
    7023             : 
    7024             :   // Create an independent environment
    7025          12 :   LocalContext context1(nullptr, templ);
    7026           6 :   context1->SetSecurityToken(password);
    7027           6 :   v8::Local<v8::Object> global1 = context1->Global();
    7028          18 :   CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
    7029             :             .FromJust());
    7030          12 :   CHECK(!global0->Equals(context1.local(), global1).FromJust());
    7031          24 :   CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
    7032             :                      .ToLocalChecked()
    7033             :                      ->Int32Value(context0.local())
    7034             :                      .FromJust());
    7035          24 :   CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
    7036             :                      .ToLocalChecked()
    7037             :                      ->Int32Value(context1.local())
    7038             :                      .FromJust());
    7039             : 
    7040             :   // Now create a new context with the old global
    7041          12 :   LocalContext context2(nullptr, templ, global1);
    7042           6 :   context2->SetSecurityToken(password);
    7043           6 :   v8::Local<v8::Object> global2 = context2->Global();
    7044          12 :   CHECK(global1->Equals(context2.local(), global2).FromJust());
    7045          24 :   CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
    7046             :                   .ToLocalChecked()
    7047             :                   ->Int32Value(context1.local())
    7048             :                   .FromJust());
    7049          24 :   CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
    7050             :                   .ToLocalChecked()
    7051             :                   ->Int32Value(context2.local())
    7052           6 :                   .FromJust());
    7053           6 : }
    7054             : 
    7055             : 
    7056       28343 : THREADED_TEST(FunctionPrototypeAcrossContexts) {
    7057             :   // Make sure that functions created by cloning boilerplates cannot
    7058             :   // communicate through their __proto__ field.
    7059             : 
    7060           6 :   v8::HandleScope scope(CcTest::isolate());
    7061             : 
    7062          12 :   LocalContext env0;
    7063           6 :   v8::Local<v8::Object> global0 = env0->Global();
    7064          18 :   v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
    7065           6 :                                       .ToLocalChecked()
    7066             :                                       .As<v8::Object>();
    7067             :   v8::Local<v8::Object> tostring0 =
    7068          18 :       object0->Get(env0.local(), v8_str("toString"))
    7069           6 :           .ToLocalChecked()
    7070             :           .As<v8::Object>();
    7071             :   v8::Local<v8::Object> proto0 =
    7072          18 :       tostring0->Get(env0.local(), v8_str("__proto__"))
    7073           6 :           .ToLocalChecked()
    7074             :           .As<v8::Object>();
    7075          18 :   CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
    7076             : 
    7077          12 :   LocalContext env1;
    7078           6 :   v8::Local<v8::Object> global1 = env1->Global();
    7079          18 :   v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
    7080           6 :                                       .ToLocalChecked()
    7081             :                                       .As<v8::Object>();
    7082             :   v8::Local<v8::Object> tostring1 =
    7083          18 :       object1->Get(env1.local(), v8_str("toString"))
    7084           6 :           .ToLocalChecked()
    7085             :           .As<v8::Object>();
    7086             :   v8::Local<v8::Object> proto1 =
    7087          18 :       tostring1->Get(env1.local(), v8_str("__proto__"))
    7088           6 :           .ToLocalChecked()
    7089             :           .As<v8::Object>();
    7090          24 :   CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
    7091           6 : }
    7092             : 
    7093             : 
    7094       28343 : THREADED_TEST(Regress892105) {
    7095             :   // Make sure that object and array literals created by cloning
    7096             :   // boilerplates cannot communicate through their __proto__
    7097             :   // field. This is rather difficult to check, but we try to add stuff
    7098             :   // to Object.prototype and Array.prototype and create a new
    7099             :   // environment. This should succeed.
    7100             : 
    7101           6 :   v8::HandleScope scope(CcTest::isolate());
    7102             : 
    7103             :   Local<String> source = v8_str(
    7104             :       "Object.prototype.obj = 1234;"
    7105             :       "Array.prototype.arr = 4567;"
    7106           6 :       "8901");
    7107             : 
    7108          12 :   LocalContext env0;
    7109           6 :   Local<Script> script0 = v8_compile(source);
    7110          24 :   CHECK_EQ(8901.0, script0->Run(env0.local())
    7111             :                        .ToLocalChecked()
    7112             :                        ->NumberValue(env0.local())
    7113             :                        .FromJust());
    7114             : 
    7115          12 :   LocalContext env1;
    7116           6 :   Local<Script> script1 = v8_compile(source);
    7117          24 :   CHECK_EQ(8901.0, script1->Run(env1.local())
    7118             :                        .ToLocalChecked()
    7119             :                        ->NumberValue(env1.local())
    7120           6 :                        .FromJust());
    7121           6 : }
    7122             : 
    7123          60 : static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7124             :   args.GetReturnValue().Set(args.This());
    7125          30 : }
    7126             : 
    7127       28343 : THREADED_TEST(UndetectableObject) {
    7128           6 :   LocalContext env;
    7129          12 :   v8::HandleScope scope(env->GetIsolate());
    7130             : 
    7131             :   Local<v8::FunctionTemplate> desc =
    7132           6 :       v8::FunctionTemplate::New(env->GetIsolate());
    7133          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7134          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7135             : 
    7136           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7137           6 :                               .ToLocalChecked()
    7138           6 :                               ->NewInstance(env.local())
    7139             :                               .ToLocalChecked();
    7140          30 :   CHECK(
    7141             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7142             : 
    7143           6 :   ExpectString("undetectable.toString()", "[object Object]");
    7144           6 :   ExpectString("typeof undetectable", "undefined");
    7145           6 :   ExpectString("typeof(undetectable)", "undefined");
    7146           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
    7147           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
    7148           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
    7149           6 :   ExpectBoolean("!undetectable", true);
    7150             : 
    7151           6 :   ExpectObject("true&&undetectable", obj);
    7152           6 :   ExpectBoolean("false&&undetectable", false);
    7153           6 :   ExpectBoolean("true||undetectable", true);
    7154           6 :   ExpectObject("false||undetectable", obj);
    7155             : 
    7156           6 :   ExpectObject("undetectable&&true", obj);
    7157           6 :   ExpectObject("undetectable&&false", obj);
    7158           6 :   ExpectBoolean("undetectable||true", true);
    7159           6 :   ExpectBoolean("undetectable||false", false);
    7160             : 
    7161           6 :   ExpectBoolean("undetectable==null", true);
    7162           6 :   ExpectBoolean("null==undetectable", true);
    7163           6 :   ExpectBoolean("undetectable==undefined", true);
    7164           6 :   ExpectBoolean("undefined==undetectable", true);
    7165           6 :   ExpectBoolean("undetectable==undetectable", true);
    7166             : 
    7167             : 
    7168           6 :   ExpectBoolean("undetectable===null", false);
    7169           6 :   ExpectBoolean("null===undetectable", false);
    7170           6 :   ExpectBoolean("undetectable===undefined", false);
    7171           6 :   ExpectBoolean("undefined===undetectable", false);
    7172          12 :   ExpectBoolean("undetectable===undetectable", true);
    7173           6 : }
    7174             : 
    7175             : 
    7176       28343 : THREADED_TEST(VoidLiteral) {
    7177           6 :   LocalContext env;
    7178           6 :   v8::Isolate* isolate = env->GetIsolate();
    7179          12 :   v8::HandleScope scope(isolate);
    7180             : 
    7181           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7182          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7183          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7184             : 
    7185           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7186           6 :                               .ToLocalChecked()
    7187           6 :                               ->NewInstance(env.local())
    7188             :                               .ToLocalChecked();
    7189          30 :   CHECK(
    7190             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7191             : 
    7192           6 :   ExpectBoolean("undefined == void 0", true);
    7193           6 :   ExpectBoolean("undetectable == void 0", true);
    7194           6 :   ExpectBoolean("null == void 0", true);
    7195           6 :   ExpectBoolean("undefined === void 0", true);
    7196           6 :   ExpectBoolean("undetectable === void 0", false);
    7197           6 :   ExpectBoolean("null === void 0", false);
    7198             : 
    7199           6 :   ExpectBoolean("void 0 == undefined", true);
    7200           6 :   ExpectBoolean("void 0 == undetectable", true);
    7201           6 :   ExpectBoolean("void 0 == null", true);
    7202           6 :   ExpectBoolean("void 0 === undefined", true);
    7203           6 :   ExpectBoolean("void 0 === undetectable", false);
    7204           6 :   ExpectBoolean("void 0 === null", false);
    7205             : 
    7206             :   ExpectString(
    7207             :       "(function() {"
    7208             :       "  try {"
    7209             :       "    return x === void 0;"
    7210             :       "  } catch(e) {"
    7211             :       "    return e.toString();"
    7212             :       "  }"
    7213             :       "})()",
    7214           6 :       "ReferenceError: x is not defined");
    7215             :   ExpectString(
    7216             :       "(function() {"
    7217             :       "  try {"
    7218             :       "    return void 0 === x;"
    7219             :       "  } catch(e) {"
    7220             :       "    return e.toString();"
    7221             :       "  }"
    7222             :       "})()",
    7223          12 :       "ReferenceError: x is not defined");
    7224           6 : }
    7225             : 
    7226             : 
    7227       28343 : THREADED_TEST(ExtensibleOnUndetectable) {
    7228           6 :   LocalContext env;
    7229           6 :   v8::Isolate* isolate = env->GetIsolate();
    7230          12 :   v8::HandleScope scope(isolate);
    7231             : 
    7232           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7233          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7234          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7235             : 
    7236           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7237           6 :                               .ToLocalChecked()
    7238           6 :                               ->NewInstance(env.local())
    7239             :                               .ToLocalChecked();
    7240          30 :   CHECK(
    7241             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7242             : 
    7243             :   Local<String> source = v8_str(
    7244             :       "undetectable.x = 42;"
    7245           6 :       "undetectable.x");
    7246             : 
    7247           6 :   Local<Script> script = v8_compile(source);
    7248             : 
    7249          24 :   CHECK(v8::Integer::New(isolate, 42)
    7250             :             ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
    7251             :             .FromJust());
    7252             : 
    7253           6 :   ExpectBoolean("Object.isExtensible(undetectable)", true);
    7254             : 
    7255           6 :   source = v8_str("Object.preventExtensions(undetectable);");
    7256           6 :   script = v8_compile(source);
    7257           6 :   script->Run(env.local()).ToLocalChecked();
    7258           6 :   ExpectBoolean("Object.isExtensible(undetectable)", false);
    7259             : 
    7260           6 :   source = v8_str("undetectable.y = 2000;");
    7261           6 :   script = v8_compile(source);
    7262           6 :   script->Run(env.local()).ToLocalChecked();
    7263          12 :   ExpectBoolean("undetectable.y == undefined", true);
    7264           6 : }
    7265             : 
    7266       28343 : THREADED_TEST(ConstructCallWithUndetectable) {
    7267           6 :   LocalContext env;
    7268           6 :   v8::Isolate* isolate = env->GetIsolate();
    7269          12 :   v8::HandleScope scope(isolate);
    7270             : 
    7271           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7272          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7273          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7274             : 
    7275           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7276           6 :                               .ToLocalChecked()
    7277           6 :                               ->NewInstance(env.local())
    7278             :                               .ToLocalChecked();
    7279          30 :   CHECK(
    7280             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7281             : 
    7282             :   // Undetectable object cannot be called as constructor.
    7283          12 :   v8::TryCatch try_catch(env->GetIsolate());
    7284           6 :   CHECK(CompileRun("new undetectable()").IsEmpty());
    7285           6 :   CHECK(try_catch.HasCaught());
    7286          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    7287           6 :   CHECK_EQ(0, strcmp("TypeError: undetectable is not a constructor",
    7288           6 :                      *exception_value));
    7289           6 : }
    7290             : 
    7291             : static int increment_callback_counter = 0;
    7292             : 
    7293          12 : static void IncrementCounterConstructCallback(
    7294          36 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7295          12 :   increment_callback_counter++;
    7296          48 :   CHECK(Local<Object>::Cast(args.NewTarget())
    7297             :             ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("counter"),
    7298             :                   v8_num(increment_callback_counter))
    7299             :             .FromJust());
    7300             :   args.GetReturnValue().Set(args.NewTarget());
    7301          12 : }
    7302             : 
    7303       28343 : THREADED_TEST(SetCallAsFunctionHandlerConstructor) {
    7304           6 :   LocalContext env;
    7305           6 :   v8::Isolate* isolate = env->GetIsolate();
    7306          12 :   v8::HandleScope scope(isolate);
    7307             : 
    7308           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7309             :   desc->InstanceTemplate()->SetCallAsFunctionHandler(
    7310          12 :       IncrementCounterConstructCallback);  // callable
    7311             : 
    7312           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7313           6 :                               .ToLocalChecked()
    7314           6 :                               ->NewInstance(env.local())
    7315             :                               .ToLocalChecked();
    7316          30 :   CHECK(env->Global()->Set(env.local(), v8_str("Counter"), obj).FromJust());
    7317             : 
    7318           6 :   ExpectInt32("(new Counter()).counter", 1);
    7319           6 :   CHECK_EQ(1, increment_callback_counter);
    7320           6 :   ExpectInt32("(new Counter()).counter", 2);
    7321          12 :   CHECK_EQ(2, increment_callback_counter);
    7322           6 : }
    7323             : // The point of this test is type checking. We run it only so compilers
    7324             : // don't complain about an unused function.
    7325       28342 : TEST(PersistentHandles) {
    7326           5 :   LocalContext env;
    7327           5 :   v8::Isolate* isolate = CcTest::isolate();
    7328          10 :   v8::HandleScope scope(isolate);
    7329           5 :   Local<String> str = v8_str("foo");
    7330             :   v8::Persistent<String> p_str(isolate, str);
    7331             :   p_str.Reset();
    7332             :   Local<Script> scr = v8_compile("");
    7333             :   v8::Persistent<Script> p_scr(isolate, scr);
    7334             :   p_scr.Reset();
    7335           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7336             :   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
    7337           5 :   p_templ.Reset();
    7338           5 : }
    7339             : 
    7340             : 
    7341           6 : static void HandleLogDelegator(
    7342             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7343           6 :   ApiTestFuzzer::Fuzz();
    7344           6 : }
    7345             : 
    7346             : 
    7347       28343 : THREADED_TEST(GlobalObjectTemplate) {
    7348           6 :   v8::Isolate* isolate = CcTest::isolate();
    7349           6 :   v8::HandleScope handle_scope(isolate);
    7350           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
    7351             :   global_template->Set(v8_str("JSNI_Log"),
    7352          18 :                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
    7353           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
    7354             :   Context::Scope context_scope(context);
    7355           6 :   CompileRun("JSNI_Log('LOG')");
    7356           6 : }
    7357             : 
    7358             : 
    7359             : static const char* kSimpleExtensionSource =
    7360             :     "function Foo() {"
    7361             :     "  return 4;"
    7362             :     "}";
    7363             : 
    7364             : 
    7365       28342 : TEST(SimpleExtensions) {
    7366           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7367           5 :   v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
    7368           5 :   const char* extension_names[] = {"simpletest"};
    7369             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7370           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7371             :   Context::Scope lock(context);
    7372             :   v8::Local<Value> result = CompileRun("Foo()");
    7373          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7374           5 :             .FromJust());
    7375           5 : }
    7376             : 
    7377             : 
    7378             : static const char* kStackTraceFromExtensionSource =
    7379             :     "function foo() {"
    7380             :     "  throw new Error();"
    7381             :     "}"
    7382             :     "function bar() {"
    7383             :     "  foo();"
    7384             :     "}";
    7385             : 
    7386             : 
    7387       28342 : TEST(StackTraceInExtension) {
    7388           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7389             :   v8::RegisterExtension(
    7390           5 :       new Extension("stacktracetest", kStackTraceFromExtensionSource));
    7391           5 :   const char* extension_names[] = {"stacktracetest"};
    7392             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7393           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7394             :   Context::Scope lock(context);
    7395             :   CompileRun(
    7396             :       "function user() { bar(); }"
    7397             :       "var error;"
    7398             :       "try{ user(); } catch (e) { error = e; }");
    7399           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
    7400           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
    7401          10 :   CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
    7402           5 : }
    7403             : 
    7404             : 
    7405       28342 : TEST(NullExtensions) {
    7406           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7407           5 :   v8::RegisterExtension(new Extension("nulltest", nullptr));
    7408           5 :   const char* extension_names[] = {"nulltest"};
    7409             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7410           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7411             :   Context::Scope lock(context);
    7412             :   v8::Local<Value> result = CompileRun("1+3");
    7413          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7414           5 :             .FromJust());
    7415           5 : }
    7416             : 
    7417             : static const char* kEmbeddedExtensionSource =
    7418             :     "function Ret54321(){return 54321;}~~@@$"
    7419             :     "$%% THIS IS A SERIES OF NON-nullptr-TERMINATED STRINGS.";
    7420             : static const int kEmbeddedExtensionSourceValidLen = 34;
    7421             : 
    7422             : 
    7423       28342 : TEST(ExtensionMissingSourceLength) {
    7424           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7425             :   v8::RegisterExtension(
    7426           5 :       new Extension("srclentest_fail", kEmbeddedExtensionSource));
    7427           5 :   const char* extension_names[] = {"srclentest_fail"};
    7428             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7429           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7430           5 :   CHECK_NULL(*context);
    7431           5 : }
    7432             : 
    7433             : 
    7434       28342 : TEST(ExtensionWithSourceLength) {
    7435          20 :   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
    7436             :        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
    7437          15 :     v8::HandleScope handle_scope(CcTest::isolate());
    7438             :     i::ScopedVector<char> extension_name(32);
    7439          15 :     i::SNPrintF(extension_name, "ext #%d", source_len);
    7440             :     v8::RegisterExtension(new Extension(extension_name.start(),
    7441             :                                         kEmbeddedExtensionSource, 0, nullptr,
    7442          15 :                                         source_len));
    7443          15 :     const char* extension_names[1] = {extension_name.start()};
    7444             :     v8::ExtensionConfiguration extensions(1, extension_names);
    7445          15 :     v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7446          15 :     if (source_len == kEmbeddedExtensionSourceValidLen) {
    7447             :       Context::Scope lock(context);
    7448           5 :       v8::Local<Value> result = CompileRun("Ret54321()");
    7449          15 :       CHECK(v8::Integer::New(CcTest::isolate(), 54321)
    7450             :                 ->Equals(context, result)
    7451             :                 .FromJust());
    7452             :     } else {
    7453             :       // Anything but exactly the right length should fail to compile.
    7454          10 :       CHECK_NULL(*context);
    7455             :     }
    7456          15 :   }
    7457           5 : }
    7458             : 
    7459             : 
    7460             : static const char* kEvalExtensionSource1 =
    7461             :     "function UseEval1() {"
    7462             :     "  var x = 42;"
    7463             :     "  return eval('x');"
    7464             :     "}";
    7465             : 
    7466             : 
    7467             : static const char* kEvalExtensionSource2 =
    7468             :     "(function() {"
    7469             :     "  var x = 42;"
    7470             :     "  function e() {"
    7471             :     "    return eval('x');"
    7472             :     "  }"
    7473             :     "  this.UseEval2 = e;"
    7474             :     "})()";
    7475             : 
    7476             : 
    7477       28342 : TEST(UseEvalFromExtension) {
    7478           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7479           5 :   v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
    7480           5 :   v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
    7481           5 :   const char* extension_names[] = {"evaltest1", "evaltest2"};
    7482             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7483           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7484             :   Context::Scope lock(context);
    7485             :   v8::Local<Value> result = CompileRun("UseEval1()");
    7486          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7487             :             .FromJust());
    7488             :   result = CompileRun("UseEval2()");
    7489          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7490           5 :             .FromJust());
    7491           5 : }
    7492             : 
    7493             : 
    7494             : static const char* kWithExtensionSource1 =
    7495             :     "function UseWith1() {"
    7496             :     "  var x = 42;"
    7497             :     "  with({x:87}) { return x; }"
    7498             :     "}";
    7499             : 
    7500             : 
    7501             : static const char* kWithExtensionSource2 =
    7502             :     "(function() {"
    7503             :     "  var x = 42;"
    7504             :     "  function e() {"
    7505             :     "    with ({x:87}) { return x; }"
    7506             :     "  }"
    7507             :     "  this.UseWith2 = e;"
    7508             :     "})()";
    7509             : 
    7510             : 
    7511       28342 : TEST(UseWithFromExtension) {
    7512           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7513           5 :   v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
    7514           5 :   v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
    7515           5 :   const char* extension_names[] = {"withtest1", "withtest2"};
    7516             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7517           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7518             :   Context::Scope lock(context);
    7519             :   v8::Local<Value> result = CompileRun("UseWith1()");
    7520          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7521             :             .FromJust());
    7522             :   result = CompileRun("UseWith2()");
    7523          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7524           5 :             .FromJust());
    7525           5 : }
    7526             : 
    7527             : 
    7528       28342 : TEST(AutoExtensions) {
    7529           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7530           5 :   Extension* extension = new Extension("autotest", kSimpleExtensionSource);
    7531             :   extension->set_auto_enable(true);
    7532           5 :   v8::RegisterExtension(extension);
    7533           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
    7534             :   Context::Scope lock(context);
    7535             :   v8::Local<Value> result = CompileRun("Foo()");
    7536          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7537           5 :             .FromJust());
    7538           5 : }
    7539             : 
    7540             : 
    7541             : static const char* kSyntaxErrorInExtensionSource = "[";
    7542             : 
    7543             : 
    7544             : // Test that a syntax error in an extension does not cause a fatal
    7545             : // error but results in an empty context.
    7546       28342 : TEST(SyntaxErrorExtensions) {
    7547           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7548             :   v8::RegisterExtension(
    7549           5 :       new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
    7550           5 :   const char* extension_names[] = {"syntaxerror"};
    7551             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7552           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7553           5 :   CHECK(context.IsEmpty());
    7554           5 : }
    7555             : 
    7556             : 
    7557             : static const char* kExceptionInExtensionSource = "throw 42";
    7558             : 
    7559             : 
    7560             : // Test that an exception when installing an extension does not cause
    7561             : // a fatal error but results in an empty context.
    7562       28342 : TEST(ExceptionExtensions) {
    7563           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7564             :   v8::RegisterExtension(
    7565           5 :       new Extension("exception", kExceptionInExtensionSource));
    7566           5 :   const char* extension_names[] = {"exception"};
    7567             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7568           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7569           5 :   CHECK(context.IsEmpty());
    7570           5 : }
    7571             : 
    7572             : static const char* kNativeCallInExtensionSource =
    7573             :     "function call_runtime_last_index_of(x) {"
    7574             :     "  return %StringLastIndexOf(x, 'bob');"
    7575             :     "}";
    7576             : 
    7577             : static const char* kNativeCallTest =
    7578             :     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
    7579             : 
    7580             : // Test that a native runtime calls are supported in extensions.
    7581       28342 : TEST(NativeCallInExtensions) {
    7582           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7583             :   v8::RegisterExtension(
    7584           5 :       new Extension("nativecall", kNativeCallInExtensionSource));
    7585           5 :   const char* extension_names[] = {"nativecall"};
    7586             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7587           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7588             :   Context::Scope lock(context);
    7589           5 :   v8::Local<Value> result = CompileRun(kNativeCallTest);
    7590          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 24))
    7591           5 :             .FromJust());
    7592           5 : }
    7593             : 
    7594             : 
    7595           0 : class NativeFunctionExtension : public Extension {
    7596             :  public:
    7597             :   NativeFunctionExtension(const char* name, const char* source,
    7598             :                           v8::FunctionCallback fun = &Echo)
    7599          15 :       : Extension(name, source), function_(fun) {}
    7600             : 
    7601           5 :   v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7602             :       v8::Isolate* isolate, v8::Local<v8::String> name) override {
    7603           5 :     return v8::FunctionTemplate::New(isolate, function_);
    7604             :   }
    7605             : 
    7606          10 :   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7607           5 :     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
    7608           5 :   }
    7609             : 
    7610             :  private:
    7611             :   v8::FunctionCallback function_;
    7612             : };
    7613             : 
    7614             : 
    7615       28342 : TEST(NativeFunctionDeclaration) {
    7616           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7617             :   const char* name = "nativedecl";
    7618             :   v8::RegisterExtension(
    7619          10 :       new NativeFunctionExtension(name, "native function foo();"));
    7620           5 :   const char* extension_names[] = {name};
    7621             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7622           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7623             :   Context::Scope lock(context);
    7624             :   v8::Local<Value> result = CompileRun("foo(42);");
    7625          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7626           5 :             .FromJust());
    7627           5 : }
    7628             : 
    7629             : 
    7630       28342 : TEST(NativeFunctionDeclarationError) {
    7631           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7632             :   const char* name = "nativedeclerr";
    7633             :   // Syntax error in extension code.
    7634             :   v8::RegisterExtension(
    7635          10 :       new NativeFunctionExtension(name, "native\nfunction foo();"));
    7636           5 :   const char* extension_names[] = {name};
    7637             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7638           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7639           5 :   CHECK(context.IsEmpty());
    7640           5 : }
    7641             : 
    7642             : 
    7643       28342 : TEST(NativeFunctionDeclarationErrorEscape) {
    7644           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7645             :   const char* name = "nativedeclerresc";
    7646             :   // Syntax error in extension code - escape code in "native" means that
    7647             :   // it's not treated as a keyword.
    7648             :   v8::RegisterExtension(
    7649          10 :       new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
    7650           5 :   const char* extension_names[] = {name};
    7651             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7652           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7653           5 :   CHECK(context.IsEmpty());
    7654           5 : }
    7655             : 
    7656             : 
    7657          30 : static void CheckDependencies(const char* name, const char* expected) {
    7658          30 :   v8::HandleScope handle_scope(CcTest::isolate());
    7659             :   v8::ExtensionConfiguration config(1, &name);
    7660          60 :   LocalContext context(&config);
    7661         210 :   CHECK(
    7662             :       v8_str(expected)
    7663             :           ->Equals(context.local(), context->Global()
    7664             :                                         ->Get(context.local(), v8_str("loaded"))
    7665             :                                         .ToLocalChecked())
    7666          30 :           .FromJust());
    7667          30 : }
    7668             : 
    7669             : 
    7670             : /*
    7671             :  * Configuration:
    7672             :  *
    7673             :  *     /-- B <--\
    7674             :  * A <-          -- D <-- E
    7675             :  *     \-- C <--/
    7676             :  */
    7677       28343 : THREADED_TEST(ExtensionDependency) {
    7678             :   static const char* kEDeps[] = {"D"};
    7679           6 :   v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
    7680             :   static const char* kDDeps[] = {"B", "C"};
    7681           6 :   v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
    7682             :   static const char* kBCDeps[] = {"A"};
    7683           6 :   v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
    7684           6 :   v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
    7685           6 :   v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
    7686           6 :   CheckDependencies("A", "undefinedA");
    7687           6 :   CheckDependencies("B", "undefinedAB");
    7688           6 :   CheckDependencies("C", "undefinedAC");
    7689           6 :   CheckDependencies("D", "undefinedABCD");
    7690           6 :   CheckDependencies("E", "undefinedABCDE");
    7691           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7692             :   static const char* exts[2] = {"C", "E"};
    7693             :   v8::ExtensionConfiguration config(2, exts);
    7694          12 :   LocalContext context(&config);
    7695          42 :   CHECK(
    7696             :       v8_str("undefinedACBDE")
    7697             :           ->Equals(context.local(), context->Global()
    7698             :                                         ->Get(context.local(), v8_str("loaded"))
    7699             :                                         .ToLocalChecked())
    7700           6 :           .FromJust());
    7701           6 : }
    7702             : 
    7703             : 
    7704             : static const char* kExtensionTestScript =
    7705             :     "native function A();"
    7706             :     "native function B();"
    7707             :     "native function C();"
    7708             :     "function Foo(i) {"
    7709             :     "  if (i == 0) return A();"
    7710             :     "  if (i == 1) return B();"
    7711             :     "  if (i == 2) return C();"
    7712             :     "}";
    7713             : 
    7714             : 
    7715         738 : static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7716         198 :   ApiTestFuzzer::Fuzz();
    7717         198 :   if (args.IsConstructCall()) {
    7718         720 :     CHECK(args.This()
    7719             :               ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
    7720             :                     args.Data())
    7721             :               .FromJust());
    7722             :     args.GetReturnValue().SetNull();
    7723         378 :     return;
    7724             :   }
    7725             :   args.GetReturnValue().Set(args.Data());
    7726             : }
    7727             : 
    7728             : 
    7729           0 : class FunctionExtension : public Extension {
    7730             :  public:
    7731          12 :   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
    7732             :   v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7733             :       v8::Isolate* isolate, v8::Local<String> name) override;
    7734             : };
    7735             : 
    7736             : 
    7737             : static int lookup_count = 0;
    7738          33 : v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
    7739             :     v8::Isolate* isolate, v8::Local<String> name) {
    7740          33 :   lookup_count++;
    7741          66 :   if (name->StrictEquals(v8_str("A"))) {
    7742             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7743          22 :                                      v8::Integer::New(isolate, 8));
    7744          44 :   } else if (name->StrictEquals(v8_str("B"))) {
    7745             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7746          22 :                                      v8::Integer::New(isolate, 7));
    7747          22 :   } else if (name->StrictEquals(v8_str("C"))) {
    7748             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7749          22 :                                      v8::Integer::New(isolate, 6));
    7750             :   } else {
    7751           0 :     return v8::Local<v8::FunctionTemplate>();
    7752             :   }
    7753             : }
    7754             : 
    7755             : 
    7756       28343 : THREADED_TEST(FunctionLookup) {
    7757           6 :   v8::RegisterExtension(new FunctionExtension());
    7758           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7759             :   static const char* exts[1] = {"functiontest"};
    7760             :   v8::ExtensionConfiguration config(1, exts);
    7761          12 :   LocalContext context(&config);
    7762           6 :   CHECK_EQ(3, lookup_count);
    7763          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7764             :             ->Equals(context.local(), CompileRun("Foo(0)"))
    7765             :             .FromJust());
    7766          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7767             :             ->Equals(context.local(), CompileRun("Foo(1)"))
    7768             :             .FromJust());
    7769          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7770             :             ->Equals(context.local(), CompileRun("Foo(2)"))
    7771           6 :             .FromJust());
    7772           6 : }
    7773             : 
    7774             : 
    7775       28343 : THREADED_TEST(NativeFunctionConstructCall) {
    7776           6 :   v8::RegisterExtension(new FunctionExtension());
    7777           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7778             :   static const char* exts[1] = {"functiontest"};
    7779             :   v8::ExtensionConfiguration config(1, exts);
    7780          12 :   LocalContext context(&config);
    7781          66 :   for (int i = 0; i < 10; i++) {
    7782             :     // Run a few times to ensure that allocation of objects doesn't
    7783             :     // change behavior of a constructor function.
    7784         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7785             :               ->Equals(context.local(), CompileRun("(new A()).data"))
    7786             :               .FromJust());
    7787         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7788             :               ->Equals(context.local(), CompileRun("(new B()).data"))
    7789             :               .FromJust());
    7790         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7791             :               ->Equals(context.local(), CompileRun("(new C()).data"))
    7792             :               .FromJust());
    7793           6 :   }
    7794           6 : }
    7795             : 
    7796             : 
    7797             : static const char* last_location;
    7798             : static const char* last_message;
    7799          10 : void StoringErrorCallback(const char* location, const char* message) {
    7800          10 :   if (last_location == nullptr) {
    7801          10 :     last_location = location;
    7802          10 :     last_message = message;
    7803             :   }
    7804          10 : }
    7805             : 
    7806             : 
    7807             : // ErrorReporting creates a circular extensions configuration and
    7808             : // tests that the fatal error handler gets called.  This renders V8
    7809             : // unusable and therefore this test cannot be run in parallel.
    7810       28342 : TEST(ErrorReporting) {
    7811           5 :   CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
    7812             :   static const char* aDeps[] = {"B"};
    7813           5 :   v8::RegisterExtension(new Extension("A", "", 1, aDeps));
    7814             :   static const char* bDeps[] = {"A"};
    7815           5 :   v8::RegisterExtension(new Extension("B", "", 1, bDeps));
    7816           5 :   last_location = nullptr;
    7817             :   v8::ExtensionConfiguration config(1, bDeps);
    7818           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
    7819           5 :   CHECK(context.IsEmpty());
    7820           5 :   CHECK(last_location);
    7821           5 : }
    7822             : 
    7823             : static size_t dcheck_count;
    7824           0 : void DcheckErrorCallback(const char* file, int line, const char* message) {
    7825           0 :   last_message = message;
    7826           0 :   ++dcheck_count;
    7827           0 : }
    7828             : 
    7829       28342 : TEST(DcheckErrorHandler) {
    7830           5 :   V8::SetDcheckErrorHandler(DcheckErrorCallback);
    7831             : 
    7832           5 :   last_message = nullptr;
    7833           5 :   dcheck_count = 0;
    7834             : 
    7835             :   DCHECK(false && "w00t");
    7836             : #ifdef DEBUG
    7837             :   CHECK_EQ(dcheck_count, 1);
    7838             :   CHECK(last_message);
    7839             :   CHECK(std::string(last_message).find("w00t") != std::string::npos);
    7840             : #else
    7841             :   // The DCHECK should be a noop in non-DEBUG builds.
    7842           5 :   CHECK_EQ(dcheck_count, 0);
    7843             : #endif
    7844           5 : }
    7845             : 
    7846           6 : static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
    7847             :                                              v8::Local<Value> data) {
    7848           6 :   v8::Isolate* isolate = CcTest::isolate();
    7849           6 :   Local<Context> context = isolate->GetCurrentContext();
    7850          12 :   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
    7851          18 :   CHECK(v8::Undefined(isolate)
    7852             :             ->Equals(context, message->GetScriptOrigin().ResourceName())
    7853             :             .FromJust());
    7854          12 :   message->GetLineNumber(context).FromJust();
    7855           6 :   message->GetSourceLine(context).ToLocalChecked();
    7856           6 : }
    7857             : 
    7858             : 
    7859       28343 : THREADED_TEST(ErrorWithMissingScriptInfo) {
    7860           6 :   LocalContext context;
    7861          12 :   v8::HandleScope scope(context->GetIsolate());
    7862           6 :   context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
    7863             :   CompileRun("throw Error()");
    7864             :   context->GetIsolate()->RemoveMessageListeners(
    7865          12 :       MissingScriptInfoMessageListener);
    7866           6 : }
    7867             : 
    7868             : 
    7869             : struct FlagAndPersistent {
    7870             :   bool flag;
    7871             :   v8::Global<v8::Object> handle;
    7872             : };
    7873             : 
    7874          80 : static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7875          40 :   data.GetParameter()->flag = true;
    7876             :   data.GetParameter()->handle.Reset();
    7877          40 : }
    7878             : 
    7879          20 : static void IndependentWeakHandle(bool global_gc, bool interlinked) {
    7880          20 :   i::FLAG_stress_incremental_marking = false;
    7881             :   // Parallel scavenge introduces too much fragmentation.
    7882          20 :   i::FLAG_parallel_scavenge = false;
    7883          20 :   v8::Isolate* iso = CcTest::isolate();
    7884          20 :   v8::HandleScope scope(iso);
    7885          20 :   v8::Local<Context> context = Context::New(iso);
    7886             :   Context::Scope context_scope(context);
    7887             : 
    7888             :   FlagAndPersistent object_a, object_b;
    7889             : 
    7890             :   size_t big_heap_size = 0;
    7891             :   size_t big_array_size = 0;
    7892             : 
    7893             :   {
    7894          20 :     v8::HandleScope handle_scope(iso);
    7895          20 :     Local<Object> a(v8::Object::New(iso));
    7896          20 :     Local<Object> b(v8::Object::New(iso));
    7897             :     object_a.handle.Reset(iso, a);
    7898             :     object_b.handle.Reset(iso, b);
    7899          20 :     if (interlinked) {
    7900          30 :       a->Set(context, v8_str("x"), b).FromJust();
    7901          30 :       b->Set(context, v8_str("x"), a).FromJust();
    7902             :     }
    7903          20 :     if (global_gc) {
    7904          10 :       CcTest::CollectAllGarbage();
    7905             :     } else {
    7906          10 :       CcTest::CollectGarbage(i::NEW_SPACE);
    7907             :     }
    7908          20 :     v8::Local<Value> big_array = v8::Array::New(CcTest::isolate(), 5000);
    7909             :     // Verify that we created an array where the space was reserved up front.
    7910             :     big_array_size =
    7911             :         v8::internal::JSArray::cast(*v8::Utils::OpenHandle(*big_array))
    7912          40 :             ->elements()
    7913          20 :             ->Size();
    7914          20 :     CHECK_LE(20000, big_array_size);
    7915          60 :     a->Set(context, v8_str("y"), big_array).FromJust();
    7916          20 :     big_heap_size = CcTest::heap()->SizeOfObjects();
    7917             :   }
    7918             : 
    7919          20 :   object_a.flag = false;
    7920          20 :   object_b.flag = false;
    7921             :   object_a.handle.SetWeak(&object_a, &SetFlag,
    7922             :                           v8::WeakCallbackType::kParameter);
    7923             :   object_b.handle.SetWeak(&object_b, &SetFlag,
    7924             :                           v8::WeakCallbackType::kParameter);
    7925             : #if __clang__
    7926             : #pragma clang diagnostic push
    7927             : #pragma clang diagnostic ignored "-Wdeprecated"
    7928             : #endif
    7929             :   // MarkIndependent is marked deprecated but we still rely on it temporarily.
    7930          20 :   CHECK(!object_b.handle.IsIndependent());
    7931             :   object_a.handle.MarkIndependent();
    7932             :   object_b.handle.MarkIndependent();
    7933          20 :   CHECK(object_b.handle.IsIndependent());
    7934             : #if __clang__
    7935             : #pragma clang diagnostic pop
    7936             : #endif
    7937          20 :   if (global_gc) {
    7938          10 :     CcTest::CollectAllGarbage();
    7939             :   } else {
    7940          10 :     CcTest::CollectGarbage(i::NEW_SPACE);
    7941             :   }
    7942             :   // A single GC should be enough to reclaim the memory, since we are using
    7943             :   // phantom handles.
    7944          20 :   CHECK_GT(big_heap_size - big_array_size, CcTest::heap()->SizeOfObjects());
    7945          20 :   CHECK(object_a.flag);
    7946          40 :   CHECK(object_b.flag);
    7947          20 : }
    7948             : 
    7949       28342 : TEST(IndependentWeakHandle) {
    7950           5 :   IndependentWeakHandle(false, false);
    7951           5 :   IndependentWeakHandle(false, true);
    7952           5 :   IndependentWeakHandle(true, false);
    7953           5 :   IndependentWeakHandle(true, true);
    7954           5 : }
    7955             : 
    7956             : class Trivial {
    7957             :  public:
    7958          12 :   explicit Trivial(int x) : x_(x) {}
    7959             : 
    7960          36 :   int x() { return x_; }
    7961          12 :   void set_x(int x) { x_ = x; }
    7962             : 
    7963             :  private:
    7964             :   int x_;
    7965             : };
    7966             : 
    7967             : 
    7968             : class Trivial2 {
    7969             :  public:
    7970          12 :   Trivial2(int x, int y) : y_(y), x_(x) {}
    7971             : 
    7972             :   int x() { return x_; }
    7973          12 :   void set_x(int x) { x_ = x; }
    7974             : 
    7975             :   int y() { return y_; }
    7976             :   void set_y(int y) { y_ = y; }
    7977             : 
    7978             :  private:
    7979             :   int y_;
    7980             :   int x_;
    7981             : };
    7982             : 
    7983          12 : void CheckInternalFields(
    7984          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
    7985             :   v8::Persistent<v8::Object>* handle = data.GetParameter();
    7986             :   handle->Reset();
    7987             :   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
    7988          12 :   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
    7989          12 :   CHECK_EQ(42, t1->x());
    7990          12 :   CHECK_EQ(103, t2->x());
    7991             :   t1->set_x(1729);
    7992             :   t2->set_x(33550336);
    7993          12 : }
    7994             : 
    7995          12 : void InternalFieldCallback(bool global_gc) {
    7996          12 :   LocalContext env;
    7997          12 :   v8::Isolate* isolate = env->GetIsolate();
    7998          24 :   v8::HandleScope scope(isolate);
    7999             : 
    8000          12 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    8001          12 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    8002             :   Trivial* t1;
    8003          24 :   Trivial2* t2;
    8004          12 :   instance_templ->SetInternalFieldCount(2);
    8005             :   v8::Persistent<v8::Object> handle;
    8006             :   {
    8007          12 :     v8::HandleScope scope(isolate);
    8008          12 :     Local<v8::Object> obj = templ->GetFunction(env.local())
    8009          12 :                                 .ToLocalChecked()
    8010          12 :                                 ->NewInstance(env.local())
    8011             :                                 .ToLocalChecked();
    8012             :     handle.Reset(isolate, obj);
    8013          12 :     CHECK_EQ(2, obj->InternalFieldCount());
    8014          12 :     CHECK(obj->GetInternalField(0)->IsUndefined());
    8015          12 :     t1 = new Trivial(42);
    8016          12 :     t2 = new Trivial2(103, 9);
    8017             : 
    8018          12 :     obj->SetAlignedPointerInInternalField(0, t1);
    8019             :     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
    8020          12 :     CHECK_EQ(42, t1->x());
    8021             : 
    8022          12 :     obj->SetAlignedPointerInInternalField(1, t2);
    8023             :     t2 =
    8024             :         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
    8025          12 :     CHECK_EQ(103, t2->x());
    8026             : 
    8027             :     handle.SetWeak<v8::Persistent<v8::Object>>(
    8028          12 :         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
    8029             :   }
    8030          12 :   if (global_gc) {
    8031           6 :     CcTest::CollectAllGarbage();
    8032             :   } else {
    8033           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    8034             :   }
    8035             : 
    8036          12 :   CHECK_EQ(1729, t1->x());
    8037          12 :   CHECK_EQ(33550336, t2->x());
    8038             : 
    8039          12 :   delete t1;
    8040          24 :   delete t2;
    8041          12 : }
    8042             : 
    8043       28343 : THREADED_TEST(InternalFieldCallback) {
    8044           6 :   InternalFieldCallback(false);
    8045           6 :   InternalFieldCallback(true);
    8046           6 : }
    8047             : 
    8048          24 : static void ResetUseValueAndSetFlag(
    8049          48 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8050             :   // Blink will reset the handle, and then use the other handle, so they
    8051             :   // can't use the same backing slot.
    8052             :   data.GetParameter()->handle.Reset();
    8053          24 :   data.GetParameter()->flag = true;
    8054          24 : }
    8055             : 
    8056          12 : void v8::internal::heap::HeapTester::ResetWeakHandle(bool global_gc) {
    8057             :   using v8::Context;
    8058             :   using v8::Local;
    8059             :   using v8::Object;
    8060             : 
    8061          12 :   v8::Isolate* iso = CcTest::isolate();
    8062          12 :   v8::HandleScope scope(iso);
    8063          12 :   v8::Local<Context> context = Context::New(iso);
    8064             :   Context::Scope context_scope(context);
    8065             : 
    8066             :   FlagAndPersistent object_a, object_b;
    8067             : 
    8068             :   {
    8069          12 :     v8::HandleScope handle_scope(iso);
    8070          12 :     Local<Object> a(v8::Object::New(iso));
    8071          12 :     Local<Object> b(v8::Object::New(iso));
    8072             :     object_a.handle.Reset(iso, a);
    8073             :     object_b.handle.Reset(iso, b);
    8074          12 :     if (global_gc) {
    8075           6 :       CcTest::PreciseCollectAllGarbage();
    8076             :     } else {
    8077           6 :       CcTest::CollectGarbage(i::NEW_SPACE);
    8078          12 :     }
    8079             :   }
    8080             : 
    8081          12 :   object_a.flag = false;
    8082          12 :   object_b.flag = false;
    8083             :   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
    8084             :                           v8::WeakCallbackType::kParameter);
    8085             :   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
    8086             :                           v8::WeakCallbackType::kParameter);
    8087          12 :   if (!global_gc) {
    8088             : #if __clang__
    8089             : #pragma clang diagnostic push
    8090             : #pragma clang diagnostic ignored "-Wdeprecated"
    8091             : #endif
    8092             :     // MarkIndependent is marked deprecated but we still rely on it temporarily.
    8093             :     object_a.handle.MarkIndependent();
    8094             :     object_b.handle.MarkIndependent();
    8095           6 :     CHECK(object_b.handle.IsIndependent());
    8096             : #if __clang__
    8097             : #pragma clang diagnostic pop
    8098             : #endif
    8099             :   }
    8100          12 :   if (global_gc) {
    8101           6 :     CcTest::PreciseCollectAllGarbage();
    8102             :   } else {
    8103           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    8104             :   }
    8105          12 :   CHECK(object_a.flag);
    8106          24 :   CHECK(object_b.flag);
    8107          12 : }
    8108             : 
    8109       28343 : THREADED_HEAP_TEST(ResetWeakHandle) {
    8110           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(false);
    8111           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(true);
    8112           6 : }
    8113             : 
    8114          24 : static void InvokeScavenge() { CcTest::CollectGarbage(i::NEW_SPACE); }
    8115             : 
    8116          24 : static void InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
    8117             : 
    8118          12 : static void ForceScavenge2(
    8119          12 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8120          12 :   data.GetParameter()->flag = true;
    8121             :   InvokeScavenge();
    8122          12 : }
    8123             : 
    8124          12 : static void ForceScavenge1(
    8125          24 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8126             :   data.GetParameter()->handle.Reset();
    8127             :   data.SetSecondPassCallback(ForceScavenge2);
    8128          12 : }
    8129             : 
    8130          12 : static void ForceMarkSweep2(
    8131          12 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8132          12 :   data.GetParameter()->flag = true;
    8133             :   InvokeMarkSweep();
    8134          12 : }
    8135             : 
    8136          12 : static void ForceMarkSweep1(
    8137          24 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8138             :   data.GetParameter()->handle.Reset();
    8139             :   data.SetSecondPassCallback(ForceMarkSweep2);
    8140          12 : }
    8141             : 
    8142       28343 : THREADED_TEST(GCFromWeakCallbacks) {
    8143           6 :   v8::Isolate* isolate = CcTest::isolate();
    8144           6 :   v8::Locker locker(CcTest::isolate());
    8145          12 :   v8::HandleScope scope(isolate);
    8146           6 :   v8::Local<Context> context = Context::New(isolate);
    8147             :   Context::Scope context_scope(context);
    8148             : 
    8149             :   static const int kNumberOfGCTypes = 2;
    8150             :   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
    8151             :   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
    8152           6 :                                                     &ForceMarkSweep1};
    8153             : 
    8154             :   typedef void (*GCInvoker)();
    8155           6 :   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
    8156             : 
    8157          18 :   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
    8158          24 :     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
    8159             :       FlagAndPersistent object;
    8160             :       {
    8161          24 :         v8::HandleScope handle_scope(isolate);
    8162          48 :         object.handle.Reset(isolate, v8::Object::New(isolate));
    8163             :       }
    8164          24 :       object.flag = false;
    8165             :       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
    8166          24 :                             v8::WeakCallbackType::kParameter);
    8167             : #if __clang__
    8168             : #pragma clang diagnostic push
    8169             : #pragma clang diagnostic ignored "-Wdeprecated"
    8170             : #endif
    8171             :       // MarkIndependent is marked deprecated but we still rely on it
    8172             :       // temporarily.
    8173             :       object.handle.MarkIndependent();
    8174             : #if __clang__
    8175             : #pragma clang diagnostic pop
    8176             : #endif
    8177          24 :       invoke_gc[outer_gc]();
    8178          24 :       EmptyMessageQueues(isolate);
    8179          24 :       CHECK(object.flag);
    8180             :     }
    8181           6 :   }
    8182           6 : }
    8183             : 
    8184             : v8::Local<Function> args_fun;
    8185             : 
    8186             : 
    8187           6 : static void ArgumentsTestCallback(
    8188          18 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    8189           6 :   ApiTestFuzzer::Fuzz();
    8190             :   v8::Isolate* isolate = args.GetIsolate();
    8191           6 :   Local<Context> context = isolate->GetCurrentContext();
    8192           6 :   CHECK_EQ(3, args.Length());
    8193          18 :   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
    8194          18 :   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
    8195          18 :   CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
    8196          12 :   CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
    8197           6 :   v8::HandleScope scope(args.GetIsolate());
    8198           6 :   CcTest::CollectAllGarbage();
    8199           6 : }
    8200             : 
    8201             : 
    8202       28343 : THREADED_TEST(Arguments) {
    8203           6 :   v8::Isolate* isolate = CcTest::isolate();
    8204           6 :   v8::HandleScope scope(isolate);
    8205           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    8206             :   global->Set(v8_str("f"),
    8207          18 :               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
    8208          12 :   LocalContext context(nullptr, global);
    8209             :   args_fun = context->Global()
    8210          24 :                  ->Get(context.local(), v8_str("f"))
    8211           6 :                  .ToLocalChecked()
    8212           6 :                  .As<Function>();
    8213          18 :   v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
    8214           6 : }
    8215             : 
    8216             : 
    8217             : static int p_getter_count;
    8218             : static int p_getter_count2;
    8219             : 
    8220             : 
    8221         240 : static void PGetter(Local<Name> name,
    8222             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    8223         240 :   ApiTestFuzzer::Fuzz();
    8224         240 :   p_getter_count++;
    8225         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8226         240 :   v8::Local<v8::Object> global = context->Global();
    8227         960 :   CHECK(
    8228             :       info.Holder()
    8229             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8230             :           .FromJust());
    8231         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8232         240 :     CHECK(info.This()
    8233             :               ->Equals(context,
    8234             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8235             :               .FromJust());
    8236         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8237         240 :     CHECK(info.This()
    8238             :               ->Equals(context,
    8239             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8240             :               .FromJust());
    8241         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8242         240 :     CHECK(info.This()
    8243             :               ->Equals(context,
    8244             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8245             :               .FromJust());
    8246         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8247         240 :     CHECK(info.This()
    8248             :               ->Equals(context,
    8249             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8250             :               .FromJust());
    8251             :   }
    8252         240 : }
    8253             : 
    8254             : 
    8255          12 : static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
    8256          12 :   ApiTestFuzzer::Fuzz();
    8257          12 :   LocalContext context;
    8258          84 :   CHECK(context->Global()
    8259             :             ->Set(context.local(), v8_str("o1"),
    8260             :                   obj->NewInstance(context.local()).ToLocalChecked())
    8261             :             .FromJust());
    8262             :   CompileRun(
    8263             :     "o1.__proto__ = { };"
    8264             :     "var o2 = { __proto__: o1 };"
    8265             :     "var o3 = { __proto__: o2 };"
    8266             :     "var o4 = { __proto__: o3 };"
    8267             :     "for (var i = 0; i < 10; i++) o4.p4;"
    8268             :     "for (var i = 0; i < 10; i++) o3.p3;"
    8269             :     "for (var i = 0; i < 10; i++) o2.p2;"
    8270          12 :     "for (var i = 0; i < 10; i++) o1.p1;");
    8271          12 : }
    8272             : 
    8273             : 
    8274         240 : static void PGetter2(Local<Name> name,
    8275             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    8276         240 :   ApiTestFuzzer::Fuzz();
    8277         240 :   p_getter_count2++;
    8278         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8279         240 :   v8::Local<v8::Object> global = context->Global();
    8280         960 :   CHECK(
    8281             :       info.Holder()
    8282             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8283             :           .FromJust());
    8284         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8285         240 :     CHECK(info.This()
    8286             :               ->Equals(context,
    8287             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8288             :               .FromJust());
    8289         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8290         240 :     CHECK(info.This()
    8291             :               ->Equals(context,
    8292             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8293             :               .FromJust());
    8294         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8295         240 :     CHECK(info.This()
    8296             :               ->Equals(context,
    8297             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8298             :               .FromJust());
    8299         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8300         240 :     CHECK(info.This()
    8301             :               ->Equals(context,
    8302             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8303             :               .FromJust());
    8304             :   }
    8305         240 : }
    8306             : 
    8307             : 
    8308       28343 : THREADED_TEST(GetterHolders) {
    8309           6 :   v8::Isolate* isolate = CcTest::isolate();
    8310           6 :   v8::HandleScope scope(isolate);
    8311           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8312          12 :   obj->SetAccessor(v8_str("p1"), PGetter);
    8313          12 :   obj->SetAccessor(v8_str("p2"), PGetter);
    8314          12 :   obj->SetAccessor(v8_str("p3"), PGetter);
    8315          12 :   obj->SetAccessor(v8_str("p4"), PGetter);
    8316           6 :   p_getter_count = 0;
    8317           6 :   RunHolderTest(obj);
    8318           6 :   CHECK_EQ(40, p_getter_count);
    8319           6 : }
    8320             : 
    8321             : 
    8322       28343 : THREADED_TEST(PreInterceptorHolders) {
    8323           6 :   v8::Isolate* isolate = CcTest::isolate();
    8324           6 :   v8::HandleScope scope(isolate);
    8325           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8326           6 :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
    8327           6 :   p_getter_count2 = 0;
    8328           6 :   RunHolderTest(obj);
    8329           6 :   CHECK_EQ(40, p_getter_count2);
    8330           6 : }
    8331             : 
    8332             : 
    8333       28343 : THREADED_TEST(ObjectInstantiation) {
    8334           6 :   v8::Isolate* isolate = CcTest::isolate();
    8335           6 :   v8::HandleScope scope(isolate);
    8336           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    8337          12 :   templ->SetAccessor(v8_str("t"), PGetter2);
    8338          12 :   LocalContext context;
    8339          36 :   CHECK(context->Global()
    8340             :             ->Set(context.local(), v8_str("o"),
    8341             :                   templ->NewInstance(context.local()).ToLocalChecked())
    8342             :             .FromJust());
    8343         600 :   for (int i = 0; i < 100; i++) {
    8344         600 :     v8::HandleScope inner_scope(CcTest::isolate());
    8345             :     v8::Local<v8::Object> obj =
    8346         600 :         templ->NewInstance(context.local()).ToLocalChecked();
    8347        3600 :     CHECK(!obj->Equals(context.local(), context->Global()
    8348             :                                             ->Get(context.local(), v8_str("o"))
    8349             :                                             .ToLocalChecked())
    8350             :                .FromJust());
    8351        3000 :     CHECK(
    8352             :         context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
    8353         600 :     v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
    8354        1800 :     CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
    8355        3000 :     CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
    8356         606 :   }
    8357           6 : }
    8358             : 
    8359             : 
    8360             : static int StrCmp16(uint16_t* a, uint16_t* b) {
    8361             :   while (true) {
    8362         168 :     if (*a == 0 && *b == 0) return 0;
    8363         138 :     if (*a != *b) return 0 + *a - *b;
    8364         132 :     a++;
    8365         132 :     b++;
    8366             :   }
    8367             : }
    8368             : 
    8369             : 
    8370             : static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
    8371             :   while (true) {
    8372         150 :     if (n-- == 0) return 0;
    8373         120 :     if (*a == 0 && *b == 0) return 0;
    8374         120 :     if (*a != *b) return 0 + *a - *b;
    8375         120 :     a++;
    8376         120 :     b++;
    8377             :   }
    8378             : }
    8379             : 
    8380         552 : int GetUtf8Length(v8::Isolate* isolate, Local<String> str) {
    8381         552 :   int len = str->Utf8Length(isolate);
    8382         552 :   if (len < 0) {
    8383             :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    8384           0 :     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
    8385           0 :     i::String::Flatten(i_isolate, istr);
    8386           0 :     len = str->Utf8Length(isolate);
    8387             :   }
    8388         552 :   return len;
    8389             : }
    8390             : 
    8391             : 
    8392       28343 : THREADED_TEST(StringWrite) {
    8393           6 :   LocalContext context;
    8394           6 :   v8::Isolate* isolate = context->GetIsolate();
    8395          12 :   v8::HandleScope scope(isolate);
    8396           6 :   v8::Local<String> str = v8_str("abcde");
    8397             :   // abc<Icelandic eth><Unicode snowman>.
    8398           6 :   v8::Local<String> str2 = v8_str("abc\xC3\xB0\xE2\x98\x83");
    8399             :   v8::Local<String> str3 =
    8400             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
    8401           6 :                               v8::NewStringType::kNormal, 7)
    8402           6 :           .ToLocalChecked();
    8403             :   // "ab" + lead surrogate + "wx" + trail surrogate + "yz"
    8404           6 :   uint16_t orphans[8] = {0x61, 0x62, 0xD800, 0x77, 0x78, 0xDC00, 0x79, 0x7A};
    8405             :   v8::Local<String> orphans_str =
    8406             :       v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
    8407           6 :                                  v8::NewStringType::kNormal, 8)
    8408           6 :           .ToLocalChecked();
    8409             :   // single lead surrogate
    8410           6 :   uint16_t lead[1] = {0xD800};
    8411             :   v8::Local<String> lead_str =
    8412             :       v8::String::NewFromTwoByte(context->GetIsolate(), lead,
    8413           6 :                                  v8::NewStringType::kNormal, 1)
    8414           6 :           .ToLocalChecked();
    8415             :   // single trail surrogate
    8416           6 :   uint16_t trail[1] = {0xDC00};
    8417             :   v8::Local<String> trail_str =
    8418             :       v8::String::NewFromTwoByte(context->GetIsolate(), trail,
    8419           6 :                                  v8::NewStringType::kNormal, 1)
    8420           6 :           .ToLocalChecked();
    8421             :   // surrogate pair
    8422           6 :   uint16_t pair[2] = {0xD800, 0xDC00};
    8423             :   v8::Local<String> pair_str =
    8424             :       v8::String::NewFromTwoByte(context->GetIsolate(), pair,
    8425           6 :                                  v8::NewStringType::kNormal, 2)
    8426           6 :           .ToLocalChecked();
    8427             :   const int kStride = 4;  // Must match stride in for loops in JS below.
    8428             :   CompileRun(
    8429             :       "var left = '';"
    8430             :       "for (var i = 0; i < 0xD800; i += 4) {"
    8431             :       "  left = left + String.fromCharCode(i);"
    8432             :       "}");
    8433             :   CompileRun(
    8434             :       "var right = '';"
    8435             :       "for (var i = 0; i < 0xD800; i += 4) {"
    8436             :       "  right = String.fromCharCode(i) + right;"
    8437             :       "}");
    8438           6 :   v8::Local<v8::Object> global = context->Global();
    8439          18 :   Local<String> left_tree = global->Get(context.local(), v8_str("left"))
    8440           6 :                                 .ToLocalChecked()
    8441             :                                 .As<String>();
    8442          18 :   Local<String> right_tree = global->Get(context.local(), v8_str("right"))
    8443           6 :                                  .ToLocalChecked()
    8444             :                                  .As<String>();
    8445             : 
    8446           6 :   CHECK_EQ(5, str2->Length());
    8447           6 :   CHECK_EQ(0xD800 / kStride, left_tree->Length());
    8448           6 :   CHECK_EQ(0xD800 / kStride, right_tree->Length());
    8449             : 
    8450             :   char buf[100];
    8451             :   char utf8buf[0xD800 * 3];
    8452             :   uint16_t wbuf[100];
    8453             :   int len;
    8454             :   int charlen;
    8455             : 
    8456             :   memset(utf8buf, 0x1, 1000);
    8457             :   len = v8::String::Empty(isolate)->WriteUtf8(isolate, utf8buf, sizeof(utf8buf),
    8458           6 :                                               &charlen);
    8459           6 :   CHECK_EQ(1, len);
    8460           6 :   CHECK_EQ(0, charlen);
    8461           6 :   CHECK_EQ(0, strcmp(utf8buf, ""));
    8462             : 
    8463             :   memset(utf8buf, 0x1, 1000);
    8464           6 :   len = str2->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen);
    8465           6 :   CHECK_EQ(9, len);
    8466           6 :   CHECK_EQ(5, charlen);
    8467           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8468             : 
    8469             :   memset(utf8buf, 0x1, 1000);
    8470           6 :   len = str2->WriteUtf8(isolate, utf8buf, 8, &charlen);
    8471           6 :   CHECK_EQ(8, len);
    8472           6 :   CHECK_EQ(5, charlen);
    8473           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83\x01", 9));
    8474             : 
    8475             :   memset(utf8buf, 0x1, 1000);
    8476           6 :   len = str2->WriteUtf8(isolate, utf8buf, 7, &charlen);
    8477           6 :   CHECK_EQ(5, len);
    8478           6 :   CHECK_EQ(4, charlen);
    8479           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8480             : 
    8481             :   memset(utf8buf, 0x1, 1000);
    8482           6 :   len = str2->WriteUtf8(isolate, utf8buf, 6, &charlen);
    8483           6 :   CHECK_EQ(5, len);
    8484           6 :   CHECK_EQ(4, charlen);
    8485           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8486             : 
    8487             :   memset(utf8buf, 0x1, 1000);
    8488           6 :   len = str2->WriteUtf8(isolate, utf8buf, 5, &charlen);
    8489           6 :   CHECK_EQ(5, len);
    8490           6 :   CHECK_EQ(4, charlen);
    8491           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8492             : 
    8493             :   memset(utf8buf, 0x1, 1000);
    8494           6 :   len = str2->WriteUtf8(isolate, utf8buf, 4, &charlen);
    8495           6 :   CHECK_EQ(3, len);
    8496           6 :   CHECK_EQ(3, charlen);
    8497           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\x01", 4));
    8498             : 
    8499             :   memset(utf8buf, 0x1, 1000);
    8500           6 :   len = str2->WriteUtf8(isolate, utf8buf, 3, &charlen);
    8501           6 :   CHECK_EQ(3, len);
    8502           6 :   CHECK_EQ(3, charlen);
    8503           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\x01", 4));
    8504             : 
    8505             :   memset(utf8buf, 0x1, 1000);
    8506           6 :   len = str2->WriteUtf8(isolate, utf8buf, 2, &charlen);
    8507           6 :   CHECK_EQ(2, len);
    8508           6 :   CHECK_EQ(2, charlen);
    8509           6 :   CHECK_EQ(0, strncmp(utf8buf, "ab\x01", 3));
    8510             : 
    8511             :   // allow orphan surrogates by default
    8512             :   memset(utf8buf, 0x1, 1000);
    8513           6 :   len = orphans_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen);
    8514           6 :   CHECK_EQ(13, len);
    8515           6 :   CHECK_EQ(8, charlen);
    8516           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\xED\xA0\x80wx\xED\xB0\x80yz"));
    8517             : 
    8518             :   // replace orphan surrogates with Unicode replacement character
    8519             :   memset(utf8buf, 0x1, 1000);
    8520             :   len = orphans_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8521           6 :                                String::REPLACE_INVALID_UTF8);
    8522           6 :   CHECK_EQ(13, len);
    8523           6 :   CHECK_EQ(8, charlen);
    8524           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\xEF\xBF\xBDwx\xEF\xBF\xBDyz"));
    8525             : 
    8526             :   // replace single lead surrogate with Unicode replacement character
    8527             :   memset(utf8buf, 0x1, 1000);
    8528             :   len = lead_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8529           6 :                             String::REPLACE_INVALID_UTF8);
    8530           6 :   CHECK_EQ(4, len);
    8531           6 :   CHECK_EQ(1, charlen);
    8532           6 :   CHECK_EQ(0, strcmp(utf8buf, "\xEF\xBF\xBD"));
    8533             : 
    8534             :   // replace single trail surrogate with Unicode replacement character
    8535             :   memset(utf8buf, 0x1, 1000);
    8536             :   len = trail_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8537           6 :                              String::REPLACE_INVALID_UTF8);
    8538           6 :   CHECK_EQ(4, len);
    8539           6 :   CHECK_EQ(1, charlen);
    8540           6 :   CHECK_EQ(0, strcmp(utf8buf, "\xEF\xBF\xBD"));
    8541             : 
    8542             :   // do not replace / write anything if surrogate pair does not fit the buffer
    8543             :   // space
    8544             :   memset(utf8buf, 0x1, 1000);
    8545             :   len = pair_str->WriteUtf8(isolate, utf8buf, 3, &charlen,
    8546           6 :                             String::REPLACE_INVALID_UTF8);
    8547           6 :   CHECK_EQ(0, len);
    8548           6 :   CHECK_EQ(0, charlen);
    8549             : 
    8550             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8551           6 :   len = GetUtf8Length(isolate, left_tree);
    8552             :   int utf8_expected =
    8553             :       (0x80 + (0x800 - 0x80) * 2 + (0xD800 - 0x800) * 3) / kStride;
    8554           6 :   CHECK_EQ(utf8_expected, len);
    8555           6 :   len = left_tree->WriteUtf8(isolate, utf8buf, utf8_expected, &charlen);
    8556           6 :   CHECK_EQ(utf8_expected, len);
    8557           6 :   CHECK_EQ(0xD800 / kStride, charlen);
    8558          12 :   CHECK_EQ(0xED, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
    8559          12 :   CHECK_EQ(0x9F, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
    8560          12 :   CHECK_EQ(0xC0 - kStride,
    8561             :            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
    8562           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8563             : 
    8564             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8565           6 :   len = GetUtf8Length(isolate, right_tree);
    8566           6 :   CHECK_EQ(utf8_expected, len);
    8567           6 :   len = right_tree->WriteUtf8(isolate, utf8buf, utf8_expected, &charlen);
    8568           6 :   CHECK_EQ(utf8_expected, len);
    8569           6 :   CHECK_EQ(0xD800 / kStride, charlen);
    8570          12 :   CHECK_EQ(0xED, static_cast<unsigned char>(utf8buf[0]));
    8571          12 :   CHECK_EQ(0x9F, static_cast<unsigned char>(utf8buf[1]));
    8572          12 :   CHECK_EQ(0xC0 - kStride, static_cast<unsigned char>(utf8buf[2]));
    8573           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8574             : 
    8575             :   memset(buf, 0x1, sizeof(buf));
    8576             :   memset(wbuf, 0x1, sizeof(wbuf));
    8577           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf));
    8578           6 :   CHECK_EQ(5, len);
    8579           6 :   len = str->Write(isolate, wbuf);
    8580           6 :   CHECK_EQ(5, len);
    8581           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8582           6 :   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8583           6 :   CHECK_EQ(0, StrCmp16(answer1, wbuf));
    8584             : 
    8585             :   memset(buf, 0x1, sizeof(buf));
    8586             :   memset(wbuf, 0x1, sizeof(wbuf));
    8587           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 4);
    8588           6 :   CHECK_EQ(4, len);
    8589           6 :   len = str->Write(isolate, wbuf, 0, 4);
    8590           6 :   CHECK_EQ(4, len);
    8591           6 :   CHECK_EQ(0, strncmp("abcd\x01", buf, 5));
    8592           6 :   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
    8593           6 :   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
    8594             : 
    8595             :   memset(buf, 0x1, sizeof(buf));
    8596             :   memset(wbuf, 0x1, sizeof(wbuf));
    8597           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 5);
    8598           6 :   CHECK_EQ(5, len);
    8599           6 :   len = str->Write(isolate, wbuf, 0, 5);
    8600           6 :   CHECK_EQ(5, len);
    8601           6 :   CHECK_EQ(0, strncmp("abcde\x01", buf, 6));
    8602           6 :   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
    8603           6 :   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
    8604             : 
    8605             :   memset(buf, 0x1, sizeof(buf));
    8606             :   memset(wbuf, 0x1, sizeof(wbuf));
    8607           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 6);
    8608           6 :   CHECK_EQ(5, len);
    8609           6 :   len = str->Write(isolate, wbuf, 0, 6);
    8610           6 :   CHECK_EQ(5, len);
    8611           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8612           6 :   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8613           6 :   CHECK_EQ(0, StrCmp16(answer4, wbuf));
    8614             : 
    8615             :   memset(buf, 0x1, sizeof(buf));
    8616             :   memset(wbuf, 0x1, sizeof(wbuf));
    8617           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, -1);
    8618           6 :   CHECK_EQ(1, len);
    8619           6 :   len = str->Write(isolate, wbuf, 4, -1);
    8620           6 :   CHECK_EQ(1, len);
    8621           6 :   CHECK_EQ(0, strcmp("e", buf));
    8622           6 :   uint16_t answer5[] = {'e', '\0'};
    8623           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8624             : 
    8625             :   memset(buf, 0x1, sizeof(buf));
    8626             :   memset(wbuf, 0x1, sizeof(wbuf));
    8627           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, 6);
    8628           6 :   CHECK_EQ(1, len);
    8629           6 :   len = str->Write(isolate, wbuf, 4, 6);
    8630           6 :   CHECK_EQ(1, len);
    8631           6 :   CHECK_EQ(0, strcmp("e", buf));
    8632           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8633             : 
    8634             :   memset(buf, 0x1, sizeof(buf));
    8635             :   memset(wbuf, 0x1, sizeof(wbuf));
    8636           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, 1);
    8637           6 :   CHECK_EQ(1, len);
    8638           6 :   len = str->Write(isolate, wbuf, 4, 1);
    8639           6 :   CHECK_EQ(1, len);
    8640           6 :   CHECK_EQ(0, strncmp("e\x01", buf, 2));
    8641           6 :   uint16_t answer6[] = {'e', 0x101};
    8642           6 :   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
    8643             : 
    8644             :   memset(buf, 0x1, sizeof(buf));
    8645             :   memset(wbuf, 0x1, sizeof(wbuf));
    8646           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 3, 1);
    8647           6 :   CHECK_EQ(1, len);
    8648           6 :   len = str->Write(isolate, wbuf, 3, 1);
    8649           6 :   CHECK_EQ(1, len);
    8650           6 :   CHECK_EQ(0, strncmp("d\x01", buf, 2));
    8651           6 :   uint16_t answer7[] = {'d', 0x101};
    8652           6 :   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
    8653             : 
    8654             :   memset(wbuf, 0x1, sizeof(wbuf));
    8655           6 :   wbuf[5] = 'X';
    8656           6 :   len = str->Write(isolate, wbuf, 0, 6, String::NO_NULL_TERMINATION);
    8657           6 :   CHECK_EQ(5, len);
    8658          12 :   CHECK_EQ('X', wbuf[5]);
    8659           6 :   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
    8660           6 :   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8661           6 :   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
    8662           6 :   CHECK_NE(0, StrCmp16(answer8b, wbuf));
    8663           6 :   wbuf[5] = '\0';
    8664           6 :   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
    8665             : 
    8666             :   memset(buf, 0x1, sizeof(buf));
    8667           6 :   buf[5] = 'X';
    8668             :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 6,
    8669           6 :                           String::NO_NULL_TERMINATION);
    8670           6 :   CHECK_EQ(5, len);
    8671           6 :   CHECK_EQ('X', buf[5]);
    8672           6 :   CHECK_EQ(0, strncmp("abcde", buf, 5));
    8673           6 :   CHECK_NE(0, strcmp("abcde", buf));
    8674           6 :   buf[5] = '\0';
    8675           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8676             : 
    8677             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8678           6 :   utf8buf[8] = 'X';
    8679             :   len = str2->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8680           6 :                         String::NO_NULL_TERMINATION);
    8681           6 :   CHECK_EQ(8, len);
    8682           6 :   CHECK_EQ('X', utf8buf[8]);
    8683           6 :   CHECK_EQ(5, charlen);
    8684           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83", 8));
    8685           6 :   CHECK_NE(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8686           6 :   utf8buf[8] = '\0';
    8687           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8688             : 
    8689             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8690           6 :   utf8buf[5] = 'X';
    8691             :   len = str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8692           6 :                        String::NO_NULL_TERMINATION);
    8693           6 :   CHECK_EQ(5, len);
    8694           6 :   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
    8695           6 :   CHECK_EQ(5, charlen);
    8696           6 :   utf8buf[5] = '\0';
    8697           6 :   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
    8698             : 
    8699             :   memset(buf, 0x1, sizeof(buf));
    8700           6 :   len = str3->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf));
    8701           6 :   CHECK_EQ(7, len);
    8702           6 :   CHECK_EQ(0, strcmp("abc", buf));
    8703           6 :   CHECK_EQ(0, buf[3]);
    8704           6 :   CHECK_EQ(0, strcmp("def", buf + 4));
    8705             : 
    8706           6 :   CHECK_EQ(0, str->WriteOneByte(isolate, nullptr, 0, 0,
    8707             :                                 String::NO_NULL_TERMINATION));
    8708           6 :   CHECK_EQ(0, str->WriteUtf8(isolate, nullptr, 0, nullptr,
    8709             :                              String::NO_NULL_TERMINATION));
    8710          12 :   CHECK_EQ(0, str->Write(isolate, nullptr, 0, 0, String::NO_NULL_TERMINATION));
    8711           6 : }
    8712             : 
    8713             : 
    8714          12 : static void Utf16Helper(
    8715             :     LocalContext& context,  // NOLINT
    8716             :     const char* name,
    8717             :     const char* lengths_name,
    8718             :     int len) {
    8719             :   Local<v8::Array> a = Local<v8::Array>::Cast(
    8720          60 :       context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
    8721             :   Local<v8::Array> alens =
    8722             :       Local<v8::Array>::Cast(context->Global()
    8723          48 :                                  ->Get(context.local(), v8_str(lengths_name))
    8724          12 :                                  .ToLocalChecked());
    8725         552 :   for (int i = 0; i < len; i++) {
    8726             :     Local<v8::String> string =
    8727        1080 :         Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
    8728             :     Local<v8::Number> expected_len = Local<v8::Number>::Cast(
    8729         540 :         alens->Get(context.local(), i).ToLocalChecked());
    8730         540 :     int length = GetUtf8Length(context->GetIsolate(), string);
    8731         540 :     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
    8732             :   }
    8733          12 : }
    8734             : 
    8735           6 : void TestUtf8DecodingAgainstReference(
    8736             :     v8::Isolate* isolate, const char* cases[],
    8737         474 :     const std::vector<std::vector<uint16_t>>& unicode_expected) {
    8738         132 :   for (size_t test_ix = 0; test_ix < unicode_expected.size(); ++test_ix) {
    8739          60 :     v8::Local<String> str = v8_str(cases[test_ix]);
    8740         180 :     CHECK_EQ(unicode_expected[test_ix].size(), str->Length());
    8741             : 
    8742          60 :     std::unique_ptr<uint16_t[]> buffer(new uint16_t[str->Length()]);
    8743          60 :     str->Write(isolate, buffer.get(), 0, -1, String::NO_NULL_TERMINATION);
    8744             : 
    8745        1044 :     for (size_t i = 0; i < unicode_expected[test_ix].size(); ++i) {
    8746         576 :       CHECK_EQ(unicode_expected[test_ix][i], buffer[i]);
    8747             :     }
    8748             :   }
    8749           6 : }
    8750             : 
    8751       28343 : THREADED_TEST(OverlongSequencesAndSurrogates) {
    8752           6 :   LocalContext context;
    8753          12 :   v8::HandleScope scope(context->GetIsolate());
    8754             : 
    8755             :   const char* cases[] = {
    8756             :       // Overlong 2-byte sequence.
    8757             :       "X\xc0\xbfY\0",
    8758             :       // Another overlong 2-byte sequence.
    8759             :       "X\xc1\xbfY\0",
    8760             :       // Overlong 3-byte sequence.
    8761             :       "X\xe0\x9f\xbfY\0",
    8762             :       // Overlong 4-byte sequence.
    8763             :       "X\xf0\x89\xbf\xbfY\0",
    8764             :       // Invalid 3-byte sequence (reserved for surrogates).
    8765             :       "X\xed\xa0\x80Y\0",
    8766             :       // Invalid 4-bytes sequence (value out of range).
    8767             :       "X\xf4\x90\x80\x80Y\0",
    8768             : 
    8769             :       // Start of an overlong 3-byte sequence but not enough continuation bytes.
    8770             :       "X\xe0\x9fY\0",
    8771             :       // Start of an overlong 4-byte sequence but not enough continuation bytes.
    8772             :       "X\xf0\x89\xbfY\0",
    8773             :       // Start of an invalid 3-byte sequence (reserved for surrogates) but not
    8774             :       // enough continuation bytes.
    8775             :       "X\xed\xa0Y\0",
    8776             :       // Start of an invalid 4-bytes sequence (value out of range) but not
    8777             :       // enough continuation bytes.
    8778             :       "X\xf4\x90\x80Y\0",
    8779           6 :   };
    8780             :   const std::vector<std::vector<uint16_t>> unicode_expected = {
    8781             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8782             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8783             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8784             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8785             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8786             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8787             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8788             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8789             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8790             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8791          12 :   };
    8792          12 :   CHECK_EQ(unicode_expected.size(), arraysize(cases));
    8793             :   TestUtf8DecodingAgainstReference(context->GetIsolate(), cases,
    8794          12 :                                    unicode_expected);
    8795           6 : }
    8796             : 
    8797       28343 : THREADED_TEST(Utf16) {
    8798           6 :   LocalContext context;
    8799          12 :   v8::HandleScope scope(context->GetIsolate());
    8800             :   CompileRun(
    8801             :       "var pad = '01234567890123456789';"
    8802             :       "var p = [];"
    8803             :       "var plens = [20, 3, 3];"
    8804             :       "p.push('01234567890123456789');"
    8805             :       "var lead = 0xD800;"
    8806             :       "var trail = 0xDC00;"
    8807             :       "p.push(String.fromCharCode(0xD800));"
    8808             :       "p.push(String.fromCharCode(0xDC00));"
    8809             :       "var a = [];"
    8810             :       "var b = [];"
    8811             :       "var c = [];"
    8812             :       "var alens = [];"
    8813             :       "for (var i = 0; i < 3; i++) {"
    8814             :       "  p[1] = String.fromCharCode(lead++);"
    8815             :       "  for (var j = 0; j < 3; j++) {"
    8816             :       "    p[2] = String.fromCharCode(trail++);"
    8817             :       "    a.push(p[i] + p[j]);"
    8818             :       "    b.push(p[i] + p[j]);"
    8819             :       "    c.push(p[i] + p[j]);"
    8820             :       "    alens.push(plens[i] + plens[j]);"
    8821             :       "  }"
    8822             :       "}"
    8823             :       "alens[5] -= 2;"  // Here the surrogate pairs match up.
    8824             :       "var a2 = [];"
    8825             :       "var b2 = [];"
    8826             :       "var c2 = [];"
    8827             :       "var a2lens = [];"
    8828             :       "for (var m = 0; m < 9; m++) {"
    8829             :       "  for (var n = 0; n < 9; n++) {"
    8830             :       "    a2.push(a[m] + a[n]);"
    8831             :       "    b2.push(b[m] + b[n]);"
    8832             :       "    var newc = 'x' + c[m] + c[n] + 'y';"
    8833             :       "    c2.push(newc.substring(1, newc.length - 1));"
    8834             :       "    var utf = alens[m] + alens[n];"  // And here.
    8835             :                                             // The 'n's that start with 0xDC..
    8836             :                                             // are 6-8 The 'm's that end with
    8837             :                                             // 0xD8.. are 1, 4 and 7
    8838             :       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
    8839             :       "    a2lens.push(utf);"
    8840             :       "  }"
    8841             :       "}");
    8842           6 :   Utf16Helper(context, "a", "alens", 9);
    8843          12 :   Utf16Helper(context, "a2", "a2lens", 81);
    8844           6 : }
    8845             : 
    8846             : 
    8847          42 : static bool SameSymbol(Local<String> s1, Local<String> s2) {
    8848             :   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
    8849             :   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
    8850          42 :   return *is1 == *is2;
    8851             : }
    8852             : 
    8853             : 
    8854       28343 : THREADED_TEST(Utf16Symbol) {
    8855           6 :   LocalContext context;
    8856          12 :   v8::HandleScope scope(context->GetIsolate());
    8857             : 
    8858             :   Local<String> symbol1 =
    8859             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8860           6 :                               v8::NewStringType::kInternalized)
    8861          12 :           .ToLocalChecked();
    8862             :   Local<String> symbol2 =
    8863             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8864           6 :                               v8::NewStringType::kInternalized)
    8865          12 :           .ToLocalChecked();
    8866           6 :   CHECK(SameSymbol(symbol1, symbol2));
    8867             : 
    8868             :   CompileRun(
    8869             :       "var sym0 = 'benedictus';"
    8870             :       "var sym0b = 'S\xC3\xB8ren';"
    8871             :       "var sym1 = '\xED\xA0\x81\xED\xB0\x87';"
    8872             :       "var sym2 = '\xF0\x90\x90\x88';"
    8873             :       "var sym3 = 'x\xED\xA0\x81\xED\xB0\x87';"
    8874             :       "var sym4 = 'x\xF0\x90\x90\x88';"
    8875             :       "if (sym1.length != 2) throw sym1;"
    8876             :       "if (sym1.charCodeAt(1) != 0xDC07) throw sym1.charCodeAt(1);"
    8877             :       "if (sym2.length != 2) throw sym2;"
    8878             :       "if (sym2.charCodeAt(1) != 0xDC08) throw sym2.charCodeAt(2);"
    8879             :       "if (sym3.length != 3) throw sym3;"
    8880             :       "if (sym3.charCodeAt(2) != 0xDC07) throw sym1.charCodeAt(2);"
    8881             :       "if (sym4.length != 3) throw sym4;"
    8882             :       "if (sym4.charCodeAt(2) != 0xDC08) throw sym2.charCodeAt(2);");
    8883             :   Local<String> sym0 =
    8884             :       v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
    8885           6 :                               v8::NewStringType::kInternalized)
    8886          12 :           .ToLocalChecked();
    8887             :   Local<String> sym0b =
    8888             :       v8::String::NewFromUtf8(context->GetIsolate(), "S\xC3\xB8ren",
    8889           6 :                               v8::NewStringType::kInternalized)
    8890          12 :           .ToLocalChecked();
    8891             :   Local<String> sym1 =
    8892             :       v8::String::NewFromUtf8(context->GetIsolate(), "\xED\xA0\x81\xED\xB0\x87",
    8893           6 :                               v8::NewStringType::kInternalized)
    8894          12 :           .ToLocalChecked();
    8895             :   Local<String> sym2 =
    8896             :       v8::String::NewFromUtf8(context->GetIsolate(), "\xF0\x90\x90\x88",
    8897           6 :                               v8::NewStringType::kInternalized)
    8898          12 :           .ToLocalChecked();
    8899             :   Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
    8900             :                                                "x\xED\xA0\x81\xED\xB0\x87",
    8901           6 :                                                v8::NewStringType::kInternalized)
    8902          12 :                            .ToLocalChecked();
    8903             :   Local<String> sym4 =
    8904             :       v8::String::NewFromUtf8(context->GetIsolate(), "x\xF0\x90\x90\x88",
    8905           6 :                               v8::NewStringType::kInternalized)
    8906          12 :           .ToLocalChecked();
    8907           6 :   v8::Local<v8::Object> global = context->Global();
    8908             :   Local<Value> s0 =
    8909          18 :       global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
    8910             :   Local<Value> s0b =
    8911          18 :       global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
    8912             :   Local<Value> s1 =
    8913          18 :       global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
    8914             :   Local<Value> s2 =
    8915          18 :       global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
    8916             :   Local<Value> s3 =
    8917          18 :       global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
    8918             :   Local<Value> s4 =
    8919          18 :       global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
    8920           6 :   CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
    8921           6 :   CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
    8922           6 :   CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
    8923           6 :   CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
    8924           6 :   CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
    8925          12 :   CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
    8926           6 : }
    8927             : 
    8928             : 
    8929       28343 : THREADED_TEST(Utf16MissingTrailing) {
    8930           6 :   LocalContext context;
    8931          12 :   v8::HandleScope scope(context->GetIsolate());
    8932             : 
    8933             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8934             :   int size = 1024 * 64;
    8935           6 :   uint8_t* buffer = new uint8_t[size];
    8936       98310 :   for (int i = 0; i < size; i += 4) {
    8937       98304 :     buffer[i] = 0xF0;
    8938       98304 :     buffer[i + 1] = 0x9D;
    8939       98304 :     buffer[i + 2] = 0x80;
    8940       98304 :     buffer[i + 3] = 0x9E;
    8941             :   }
    8942             : 
    8943             :   // Now invoke the decoder without last 3 bytes
    8944             :   v8::Local<v8::String> str =
    8945             :       v8::String::NewFromUtf8(
    8946             :           context->GetIsolate(), reinterpret_cast<char*>(buffer),
    8947           6 :           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
    8948             :   USE(str);
    8949          12 :   delete[] buffer;
    8950           6 : }
    8951             : 
    8952             : 
    8953       28343 : THREADED_TEST(Utf16Trailing3Byte) {
    8954           6 :   LocalContext context;
    8955           6 :   v8::Isolate* isolate = context->GetIsolate();
    8956          12 :   v8::HandleScope scope(isolate);
    8957             : 
    8958             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8959             :   int size = 1024 * 63;
    8960           6 :   uint8_t* buffer = new uint8_t[size];
    8961      129030 :   for (int i = 0; i < size; i += 3) {
    8962      129024 :     buffer[i] = 0xE2;
    8963      129024 :     buffer[i + 1] = 0x80;
    8964      129024 :     buffer[i + 2] = 0xA6;
    8965             :   }
    8966             : 
    8967             :   // Now invoke the decoder without last 3 bytes
    8968             :   v8::Local<v8::String> str =
    8969             :       v8::String::NewFromUtf8(isolate, reinterpret_cast<char*>(buffer),
    8970             :                               v8::NewStringType::kNormal, size)
    8971           6 :           .ToLocalChecked();
    8972             : 
    8973          12 :   v8::String::Value value(isolate, str);
    8974           6 :   CHECK_EQ(value.length(), size / 3);
    8975          12 :   CHECK_EQ((*value)[value.length() - 1], 0x2026);
    8976             : 
    8977          12 :   delete[] buffer;
    8978           6 : }
    8979             : 
    8980             : 
    8981       28343 : THREADED_TEST(ToArrayIndex) {
    8982           6 :   LocalContext context;
    8983           6 :   v8::Isolate* isolate = context->GetIsolate();
    8984          12 :   v8::HandleScope scope(isolate);
    8985             : 
    8986           6 :   v8::Local<String> str = v8_str("42");
    8987           6 :   v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
    8988           6 :   CHECK(!index.IsEmpty());
    8989          18 :   CHECK_EQ(42.0,
    8990             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    8991           6 :   str = v8_str("42asdf");
    8992           6 :   index = str->ToArrayIndex(context.local());
    8993           6 :   CHECK(index.IsEmpty());
    8994           6 :   str = v8_str("-42");
    8995           6 :   index = str->ToArrayIndex(context.local());
    8996           6 :   CHECK(index.IsEmpty());
    8997           6 :   str = v8_str("4294967294");
    8998           6 :   index = str->ToArrayIndex(context.local());
    8999           6 :   CHECK(!index.IsEmpty());
    9000          18 :   CHECK_EQ(4294967294.0,
    9001             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9002           6 :   v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
    9003           6 :   index = num->ToArrayIndex(context.local());
    9004           6 :   CHECK(!index.IsEmpty());
    9005          18 :   CHECK_EQ(1.0,
    9006             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9007           6 :   num = v8::Number::New(isolate, -1);
    9008           6 :   index = num->ToArrayIndex(context.local());
    9009           6 :   CHECK(index.IsEmpty());
    9010           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    9011          12 :   index = obj->ToArrayIndex(context.local());
    9012          12 :   CHECK(index.IsEmpty());
    9013           6 : }
    9014             : 
    9015           6 : static v8::MaybeLocal<Value> PrepareStackTrace42(v8::Local<Context> context,
    9016             :                                                  v8::Local<Value> error,
    9017             :                                                  v8::Local<Array> trace) {
    9018           6 :   return v8::Number::New(context->GetIsolate(), 42);
    9019             : }
    9020             : 
    9021           6 : static v8::MaybeLocal<Value> PrepareStackTraceThrow(v8::Local<Context> context,
    9022             :                                                     v8::Local<Value> error,
    9023             :                                                     v8::Local<Array> trace) {
    9024           6 :   v8::Isolate* isolate = context->GetIsolate();
    9025           6 :   v8::Local<String> message = v8_str("42");
    9026           6 :   isolate->ThrowException(v8::Exception::Error(message));
    9027           6 :   return v8::MaybeLocal<Value>();
    9028             : }
    9029             : 
    9030       28343 : THREADED_TEST(IsolatePrepareStackTrace) {
    9031           6 :   LocalContext context;
    9032           6 :   v8::Isolate* isolate = context->GetIsolate();
    9033          12 :   v8::HandleScope scope(isolate);
    9034             : 
    9035           6 :   isolate->SetPrepareStackTraceCallback(PrepareStackTrace42);
    9036             : 
    9037             :   v8::Local<Value> v = CompileRun("new Error().stack");
    9038             : 
    9039           6 :   CHECK(v->IsNumber());
    9040          18 :   CHECK_EQ(v.As<v8::Number>()->Int32Value(context.local()).FromJust(), 42);
    9041           6 : }
    9042             : 
    9043       28343 : THREADED_TEST(IsolatePrepareStackTraceThrow) {
    9044           6 :   LocalContext context;
    9045           6 :   v8::Isolate* isolate = context->GetIsolate();
    9046          12 :   v8::HandleScope scope(isolate);
    9047             : 
    9048           6 :   isolate->SetPrepareStackTraceCallback(PrepareStackTraceThrow);
    9049             : 
    9050             :   v8::Local<Value> v = CompileRun("try { new Error().stack } catch (e) { e }");
    9051             : 
    9052           6 :   CHECK(v->IsNativeError());
    9053             : 
    9054          12 :   v8::Local<String> message = v8::Exception::CreateMessage(isolate, v)->Get();
    9055             : 
    9056          18 :   CHECK(message->StrictEquals(v8_str("Uncaught Error: 42")));
    9057           6 : }
    9058             : 
    9059       28343 : THREADED_TEST(ErrorConstruction) {
    9060           6 :   LocalContext context;
    9061          12 :   v8::HandleScope scope(context->GetIsolate());
    9062             : 
    9063           6 :   v8::Local<String> foo = v8_str("foo");
    9064           6 :   v8::Local<String> message = v8_str("message");
    9065           6 :   v8::Local<Value> range_error = v8::Exception::RangeError(foo);
    9066           6 :   CHECK(range_error->IsObject());
    9067          24 :   CHECK(range_error.As<v8::Object>()
    9068             :             ->Get(context.local(), message)
    9069             :             .ToLocalChecked()
    9070             :             ->Equals(context.local(), foo)
    9071             :             .FromJust());
    9072           6 :   v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
    9073           6 :   CHECK(reference_error->IsObject());
    9074          24 :   CHECK(reference_error.As<v8::Object>()
    9075             :             ->Get(context.local(), message)
    9076             :             .ToLocalChecked()
    9077             :             ->Equals(context.local(), foo)
    9078             :             .FromJust());
    9079           6 :   v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
    9080           6 :   CHECK(syntax_error->IsObject());
    9081          24 :   CHECK(syntax_error.As<v8::Object>()
    9082             :             ->Get(context.local(), message)
    9083             :             .ToLocalChecked()
    9084             :             ->Equals(context.local(), foo)
    9085             :             .FromJust());
    9086           6 :   v8::Local<Value> type_error = v8::Exception::TypeError(foo);
    9087           6 :   CHECK(type_error->IsObject());
    9088          24 :   CHECK(type_error.As<v8::Object>()
    9089             :             ->Get(context.local(), message)
    9090             :             .ToLocalChecked()
    9091             :             ->Equals(context.local(), foo)
    9092             :             .FromJust());
    9093           6 :   v8::Local<Value> error = v8::Exception::Error(foo);
    9094           6 :   CHECK(error->IsObject());
    9095          24 :   CHECK(error.As<v8::Object>()
    9096             :             ->Get(context.local(), message)
    9097             :             .ToLocalChecked()
    9098             :             ->Equals(context.local(), foo)
    9099           6 :             .FromJust());
    9100           6 : }
    9101             : 
    9102             : 
    9103          48 : static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9104          12 :   ApiTestFuzzer::Fuzz();
    9105          12 :   v8::Local<String> foo = v8_str("foo");
    9106          12 :   v8::Local<String> message = v8_str("message");
    9107          12 :   v8::Local<Value> error = v8::Exception::Error(foo);
    9108          12 :   CHECK(error->IsObject());
    9109          12 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9110          36 :   CHECK(error.As<v8::Object>()
    9111             :             ->Get(context, message)
    9112             :             .ToLocalChecked()
    9113             :             ->Equals(context, foo)
    9114             :             .FromJust());
    9115          12 :   info.GetIsolate()->ThrowException(error);
    9116             :   info.GetReturnValue().SetUndefined();
    9117          12 : }
    9118             : 
    9119             : 
    9120       28343 : THREADED_TEST(ExceptionCreateMessage) {
    9121           6 :   LocalContext context;
    9122          12 :   v8::HandleScope scope(context->GetIsolate());
    9123           6 :   v8::Local<String> foo_str = v8_str("foo");
    9124           6 :   v8::Local<String> message_str = v8_str("message");
    9125             : 
    9126           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
    9127             : 
    9128             :   Local<v8::FunctionTemplate> fun =
    9129           6 :       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
    9130           6 :   v8::Local<v8::Object> global = context->Global();
    9131          36 :   CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
    9132             :                     fun->GetFunction(context.local()).ToLocalChecked())
    9133             :             .FromJust());
    9134             : 
    9135          12 :   TryCatch try_catch(context->GetIsolate());
    9136             :   CompileRun(
    9137             :       "function f1() {\n"
    9138             :       "  throwV8Exception();\n"
    9139             :       "};\n"
    9140             :       "f1();");
    9141           6 :   CHECK(try_catch.HasCaught());
    9142             : 
    9143           6 :   v8::Local<v8::Value> error = try_catch.Exception();
    9144           6 :   CHECK(error->IsObject());
    9145          24 :   CHECK(error.As<v8::Object>()
    9146             :             ->Get(context.local(), message_str)
    9147             :             .ToLocalChecked()
    9148             :             ->Equals(context.local(), foo_str)
    9149             :             .FromJust());
    9150             : 
    9151             :   v8::Local<v8::Message> message =
    9152           6 :       v8::Exception::CreateMessage(context->GetIsolate(), error);
    9153           6 :   CHECK(!message.IsEmpty());
    9154          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    9155          12 :   CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
    9156             : 
    9157           6 :   v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
    9158           6 :   CHECK(!stackTrace.IsEmpty());
    9159           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    9160             : 
    9161           6 :   stackTrace = v8::Exception::GetStackTrace(error);
    9162           6 :   CHECK(!stackTrace.IsEmpty());
    9163           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    9164             : 
    9165           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
    9166             : 
    9167             :   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
    9168             :   // is false.
    9169           6 :   try_catch.Reset();
    9170             : 
    9171             :   CompileRun(
    9172             :       "function f2() {\n"
    9173             :       "  return throwV8Exception();\n"
    9174             :       "};\n"
    9175             :       "f2();");
    9176           6 :   CHECK(try_catch.HasCaught());
    9177             : 
    9178           6 :   error = try_catch.Exception();
    9179           6 :   CHECK(error->IsObject());
    9180          24 :   CHECK(error.As<v8::Object>()
    9181             :             ->Get(context.local(), message_str)
    9182             :             .ToLocalChecked()
    9183             :             ->Equals(context.local(), foo_str)
    9184             :             .FromJust());
    9185             : 
    9186           6 :   message = v8::Exception::CreateMessage(context->GetIsolate(), error);
    9187           6 :   CHECK(!message.IsEmpty());
    9188          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    9189          12 :   CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
    9190             : 
    9191             :   // Should be empty stack trace.
    9192           6 :   stackTrace = message->GetStackTrace();
    9193           6 :   CHECK(stackTrace.IsEmpty());
    9194          18 :   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
    9195           6 : }
    9196             : 
    9197             : 
    9198       28343 : THREADED_TEST(ExceptionCreateMessageLength) {
    9199           6 :   LocalContext context;
    9200          12 :   v8::HandleScope scope(context->GetIsolate());
    9201             : 
    9202             :   // Test that the message is not truncated.
    9203          12 :   TryCatch try_catch(context->GetIsolate());
    9204             :   CompileRun(
    9205             :       "var message = 'm';"
    9206             :       "while (message.length < 1000) message += message;"
    9207             :       "throw message;");
    9208           6 :   CHECK(try_catch.HasCaught());
    9209             : 
    9210          24 :   CHECK_LT(1000, try_catch.Message()->Get()->Length());
    9211           6 : }
    9212             : 
    9213             : 
    9214           0 : static void YGetter(Local<String> name,
    9215             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    9216           0 :   ApiTestFuzzer::Fuzz();
    9217           0 :   info.GetReturnValue().Set(v8_num(10));
    9218           0 : }
    9219             : 
    9220             : 
    9221           6 : static void YSetter(Local<String> name,
    9222             :                     Local<Value> value,
    9223             :                     const v8::PropertyCallbackInfo<void>& info) {
    9224             :   Local<Object> this_obj = Local<Object>::Cast(info.This());
    9225           6 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9226          12 :   if (this_obj->Has(context, name).FromJust())
    9227          12 :     this_obj->Delete(context, name).FromJust();
    9228          12 :   CHECK(this_obj->Set(context, name, value).FromJust());
    9229           6 : }
    9230             : 
    9231             : 
    9232       28343 : THREADED_TEST(DeleteAccessor) {
    9233           6 :   v8::Isolate* isolate = CcTest::isolate();
    9234           6 :   v8::HandleScope scope(isolate);
    9235           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    9236           6 :   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
    9237          12 :   LocalContext context;
    9238             :   v8::Local<v8::Object> holder =
    9239           6 :       obj->NewInstance(context.local()).ToLocalChecked();
    9240          30 :   CHECK(context->Global()
    9241             :             ->Set(context.local(), v8_str("holder"), holder)
    9242             :             .FromJust());
    9243             :   v8::Local<Value> result =
    9244             :       CompileRun("holder.y = 11; holder.y = 12; holder.y");
    9245          18 :   CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
    9246           6 : }
    9247             : 
    9248             : 
    9249             : static int trouble_nesting = 0;
    9250          45 : static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9251          15 :   ApiTestFuzzer::Fuzz();
    9252          15 :   trouble_nesting++;
    9253             : 
    9254             :   // Call a JS function that throws an uncaught exception.
    9255          15 :   Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    9256          15 :   Local<v8::Object> arg_this = context->Global();
    9257             :   Local<Value> trouble_callee =
    9258          15 :       (trouble_nesting == 3)
    9259          30 :           ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
    9260          60 :           : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
    9261          15 :   CHECK(trouble_callee->IsFunction());
    9262             :   args.GetReturnValue().Set(Function::Cast(*trouble_callee)
    9263          15 :                                 ->Call(context, arg_this, 0, nullptr)
    9264          30 :                                 .FromMaybe(v8::Local<v8::Value>()));
    9265          15 : }
    9266             : 
    9267             : 
    9268             : static int report_count = 0;
    9269           5 : static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
    9270             :                                              v8::Local<Value>) {
    9271           5 :   report_count++;
    9272           5 : }
    9273             : 
    9274             : 
    9275             : // Counts uncaught exceptions, but other tests running in parallel
    9276             : // also have uncaught exceptions.
    9277       28342 : TEST(ApiUncaughtException) {
    9278           5 :   report_count = 0;
    9279           5 :   LocalContext env;
    9280           5 :   v8::Isolate* isolate = env->GetIsolate();
    9281          10 :   v8::HandleScope scope(isolate);
    9282           5 :   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
    9283             : 
    9284             :   Local<v8::FunctionTemplate> fun =
    9285           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9286           5 :   v8::Local<v8::Object> global = env->Global();
    9287          25 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9288             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9289             :             .FromJust());
    9290             : 
    9291             :   CompileRun(
    9292             :       "function trouble_callee() {"
    9293             :       "  var x = null;"
    9294             :       "  return x.foo;"
    9295             :       "};"
    9296             :       "function trouble_caller() {"
    9297             :       "  trouble();"
    9298             :       "};");
    9299             :   Local<Value> trouble =
    9300          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9301           5 :   CHECK(trouble->IsFunction());
    9302             :   Local<Value> trouble_callee =
    9303          15 :       global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
    9304           5 :   CHECK(trouble_callee->IsFunction());
    9305             :   Local<Value> trouble_caller =
    9306          15 :       global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
    9307           5 :   CHECK(trouble_caller->IsFunction());
    9308             :   Function::Cast(*trouble_caller)
    9309          10 :       ->Call(env.local(), global, 0, nullptr)
    9310           5 :       .FromMaybe(v8::Local<v8::Value>());
    9311           5 :   CHECK_EQ(1, report_count);
    9312          10 :   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
    9313           5 : }
    9314             : 
    9315             : 
    9316             : static const char* script_resource_name = "ExceptionInNativeScript.js";
    9317           5 : static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
    9318             :                                                 v8::Local<Value>) {
    9319           5 :   v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
    9320          10 :   CHECK(!name_val.IsEmpty() && name_val->IsString());
    9321             :   v8::String::Utf8Value name(v8::Isolate::GetCurrent(),
    9322           5 :                              message->GetScriptOrigin().ResourceName());
    9323           5 :   CHECK_EQ(0, strcmp(script_resource_name, *name));
    9324             :   v8::Local<v8::Context> context =
    9325           5 :       v8::Isolate::GetCurrent()->GetCurrentContext();
    9326          10 :   CHECK_EQ(3, message->GetLineNumber(context).FromJust());
    9327             :   v8::String::Utf8Value source_line(
    9328             :       v8::Isolate::GetCurrent(),
    9329          15 :       message->GetSourceLine(context).ToLocalChecked());
    9330          10 :   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
    9331           5 : }
    9332             : 
    9333             : 
    9334       28342 : TEST(ExceptionInNativeScript) {
    9335           5 :   LocalContext env;
    9336           5 :   v8::Isolate* isolate = env->GetIsolate();
    9337          10 :   v8::HandleScope scope(isolate);
    9338           5 :   isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
    9339             : 
    9340             :   Local<v8::FunctionTemplate> fun =
    9341           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9342           5 :   v8::Local<v8::Object> global = env->Global();
    9343          25 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9344             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9345             :             .FromJust());
    9346             : 
    9347             :   CompileRunWithOrigin(
    9348             :       "function trouble() {\n"
    9349             :       "  var o = {};\n"
    9350             :       "  new o.foo();\n"
    9351             :       "};",
    9352           5 :       script_resource_name);
    9353             :   Local<Value> trouble =
    9354          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9355           5 :   CHECK(trouble->IsFunction());
    9356          10 :   CHECK(Function::Cast(*trouble)
    9357             :             ->Call(env.local(), global, 0, nullptr)
    9358             :             .IsEmpty());
    9359          10 :   isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
    9360           5 : }
    9361             : 
    9362             : 
    9363       28342 : TEST(CompilationErrorUsingTryCatchHandler) {
    9364           5 :   LocalContext env;
    9365          10 :   v8::HandleScope scope(env->GetIsolate());
    9366          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9367             :   v8_compile("This doesn't &*&@#$&*^ compile.");
    9368          10 :   CHECK(*try_catch.Exception());
    9369          10 :   CHECK(try_catch.HasCaught());
    9370           5 : }
    9371             : 
    9372             : 
    9373       28342 : TEST(TryCatchFinallyUsingTryCatchHandler) {
    9374           5 :   LocalContext env;
    9375          10 :   v8::HandleScope scope(env->GetIsolate());
    9376          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9377             :   CompileRun("try { throw ''; } catch (e) {}");
    9378           5 :   CHECK(!try_catch.HasCaught());
    9379             :   CompileRun("try { throw ''; } finally {}");
    9380           5 :   CHECK(try_catch.HasCaught());
    9381           5 :   try_catch.Reset();
    9382             :   CompileRun(
    9383             :       "(function() {"
    9384             :       "try { throw ''; } finally { return; }"
    9385             :       "})()");
    9386           5 :   CHECK(!try_catch.HasCaught());
    9387             :   CompileRun(
    9388             :       "(function()"
    9389             :       "  { try { throw ''; } finally { throw 0; }"
    9390             :       "})()");
    9391          10 :   CHECK(try_catch.HasCaught());
    9392           5 : }
    9393             : 
    9394             : 
    9395          20 : void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9396          10 :   v8::HandleScope scope(args.GetIsolate());
    9397             :   CompileRun(args[0]
    9398          10 :                  ->ToString(args.GetIsolate()->GetCurrentContext())
    9399          20 :                  .ToLocalChecked());
    9400          10 : }
    9401             : 
    9402             : 
    9403       28342 : TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
    9404           5 :   v8::Isolate* isolate = CcTest::isolate();
    9405           5 :   v8::HandleScope scope(isolate);
    9406           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    9407             :   templ->Set(v8_str("CEvaluate"),
    9408          15 :              v8::FunctionTemplate::New(isolate, CEvaluate));
    9409          10 :   LocalContext context(nullptr, templ);
    9410          10 :   v8::TryCatch try_catch(isolate);
    9411             :   CompileRun("try {"
    9412             :              "  CEvaluate('throw 1;');"
    9413             :              "} finally {"
    9414             :              "}");
    9415           5 :   CHECK(try_catch.HasCaught());
    9416          10 :   CHECK(!try_catch.Message().IsEmpty());
    9417          10 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    9418           5 :   CHECK_EQ(0, strcmp(*exception_value, "1"));
    9419           5 :   try_catch.Reset();
    9420             :   CompileRun("try {"
    9421             :              "  CEvaluate('throw 1;');"
    9422             :              "} finally {"
    9423             :              "  throw 2;"
    9424             :              "}");
    9425           5 :   CHECK(try_catch.HasCaught());
    9426          10 :   CHECK(!try_catch.Message().IsEmpty());
    9427          10 :   String::Utf8Value finally_exception_value(isolate, try_catch.Exception());
    9428          10 :   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
    9429           5 : }
    9430             : 
    9431             : 
    9432             : // For use within the TestSecurityHandler() test.
    9433             : static bool g_security_callback_result = false;
    9434          35 : static bool SecurityTestCallback(Local<v8::Context> accessing_context,
    9435             :                                  Local<v8::Object> accessed_object,
    9436             :                                  Local<v8::Value> data) {
    9437             :   printf("a\n");
    9438          35 :   CHECK(!data.IsEmpty() && data->IsInt32());
    9439          70 :   CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
    9440          35 :   return g_security_callback_result;
    9441             : }
    9442             : 
    9443             : 
    9444             : // SecurityHandler can't be run twice
    9445       28342 : TEST(SecurityHandler) {
    9446           5 :   v8::Isolate* isolate = CcTest::isolate();
    9447           5 :   v8::HandleScope scope0(isolate);
    9448             :   v8::Local<v8::ObjectTemplate> global_template =
    9449           5 :       v8::ObjectTemplate::New(isolate);
    9450          10 :   global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
    9451             :   // Create an environment
    9452           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
    9453           5 :   context0->Enter();
    9454             : 
    9455           5 :   v8::Local<v8::Object> global0 = context0->Global();
    9456             :   v8::Local<Script> script0 = v8_compile("foo = 111");
    9457           5 :   script0->Run(context0).ToLocalChecked();
    9458          15 :   CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
    9459             :   v8::Local<Value> foo0 =
    9460          15 :       global0->Get(context0, v8_str("foo")).ToLocalChecked();
    9461          10 :   CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
    9462          15 :   v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
    9463          10 :   CHECK_EQ(999, z0->Int32Value(context0).FromJust());
    9464             : 
    9465             :   // Create another environment, should fail security checks.
    9466          10 :   v8::HandleScope scope1(isolate);
    9467             : 
    9468           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, global_template);
    9469           5 :   context1->Enter();
    9470             : 
    9471           5 :   v8::Local<v8::Object> global1 = context1->Global();
    9472          15 :   global1->Set(context1, v8_str("othercontext"), global0).FromJust();
    9473             :   // This set will fail the security check.
    9474             :   v8::Local<Script> script1 =
    9475             :       v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
    9476          10 :   CHECK(script1->Run(context1).IsEmpty());
    9477           5 :   g_security_callback_result = true;
    9478             :   // This read will pass the security check.
    9479             :   v8::Local<Value> foo1 =
    9480          15 :       global0->Get(context1, v8_str("foo")).ToLocalChecked();
    9481          10 :   CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
    9482             :   // This read will pass the security check.
    9483          15 :   v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
    9484          10 :   CHECK_EQ(999, z1->Int32Value(context1).FromJust());
    9485             : 
    9486             :   // Create another environment, should pass security checks.
    9487             :   {
    9488           5 :     v8::HandleScope scope2(isolate);
    9489          10 :     LocalContext context2;
    9490           5 :     v8::Local<v8::Object> global2 = context2->Global();
    9491          20 :     CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
    9492             :               .FromJust());
    9493             :     v8::Local<Script> script2 =
    9494             :         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
    9495           5 :     script2->Run(context2.local()).ToLocalChecked();
    9496             :     v8::Local<Value> foo2 =
    9497          15 :         global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
    9498          10 :     CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
    9499             :     v8::Local<Value> z2 =
    9500          15 :         global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
    9501          15 :     CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
    9502             :   }
    9503             : 
    9504           5 :   context1->Exit();
    9505          10 :   context0->Exit();
    9506           5 : }
    9507             : 
    9508             : 
    9509       28343 : THREADED_TEST(SecurityChecks) {
    9510           6 :   LocalContext env1;
    9511          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9512           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9513             : 
    9514           6 :   Local<Value> foo = v8_str("foo");
    9515           6 :   Local<Value> bar = v8_str("bar");
    9516             : 
    9517             :   // Set to the same domain.
    9518           6 :   env1->SetSecurityToken(foo);
    9519             : 
    9520             :   // Create a function in env1.
    9521             :   CompileRun("spy=function(){return spy;}");
    9522             :   Local<Value> spy =
    9523          30 :       env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
    9524           6 :   CHECK(spy->IsFunction());
    9525             : 
    9526             :   // Create another function accessing global objects.
    9527             :   CompileRun("spy2=function(){return new this.Array();}");
    9528             :   Local<Value> spy2 =
    9529          30 :       env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
    9530           6 :   CHECK(spy2->IsFunction());
    9531             : 
    9532             :   // Switch to env2 in the same domain and invoke spy on env2.
    9533             :   {
    9534           6 :     env2->SetSecurityToken(foo);
    9535             :     // Enter env2
    9536             :     Context::Scope scope_env2(env2);
    9537             :     Local<Value> result = Function::Cast(*spy)
    9538          12 :                               ->Call(env2, env2->Global(), 0, nullptr)
    9539           6 :                               .ToLocalChecked();
    9540           6 :     CHECK(result->IsFunction());
    9541             :   }
    9542             : 
    9543             :   {
    9544           6 :     env2->SetSecurityToken(bar);
    9545             :     Context::Scope scope_env2(env2);
    9546             : 
    9547             :     // Call cross_domain_call, it should throw an exception
    9548          12 :     v8::TryCatch try_catch(env1->GetIsolate());
    9549          18 :     CHECK(Function::Cast(*spy2)
    9550             :               ->Call(env2, env2->Global(), 0, nullptr)
    9551             :               .IsEmpty());
    9552           6 :     CHECK(try_catch.HasCaught());
    9553           6 :   }
    9554           6 : }
    9555             : 
    9556             : 
    9557             : // Regression test case for issue 1183439.
    9558       28343 : THREADED_TEST(SecurityChecksForPrototypeChain) {
    9559           6 :   LocalContext current;
    9560          12 :   v8::HandleScope scope(current->GetIsolate());
    9561           6 :   v8::Local<Context> other = Context::New(current->GetIsolate());
    9562             : 
    9563             :   // Change context to be able to get to the Object function in the
    9564             :   // other context without hitting the security checks.
    9565             :   v8::Local<Value> other_object;
    9566             :   { Context::Scope scope(other);
    9567             :     other_object =
    9568          24 :         other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
    9569          18 :     CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
    9570             :   }
    9571             : 
    9572          36 :   CHECK(current->Global()
    9573             :             ->Set(current.local(), v8_str("other"), other->Global())
    9574             :             .FromJust());
    9575          30 :   CHECK(v8_compile("other")
    9576             :             ->Run(current.local())
    9577             :             .ToLocalChecked()
    9578             :             ->Equals(current.local(), other->Global())
    9579             :             .FromJust());
    9580             : 
    9581             :   // Make sure the security check fails here and we get an undefined
    9582             :   // result instead of getting the Object function. Repeat in a loop
    9583             :   // to make sure to exercise the IC code.
    9584             :   v8::Local<Script> access_other0 = v8_compile("other.Object");
    9585             :   v8::Local<Script> access_other1 = v8_compile("other[42]");
    9586          36 :   for (int i = 0; i < 5; i++) {
    9587          60 :     CHECK(access_other0->Run(current.local()).IsEmpty());
    9588          60 :     CHECK(access_other1->Run(current.local()).IsEmpty());
    9589             :   }
    9590             : 
    9591             :   // Create an object that has 'other' in its prototype chain and make
    9592             :   // sure we cannot access the Object function indirectly through
    9593             :   // that. Repeat in a loop to make sure to exercise the IC code.
    9594             :   v8_compile(
    9595             :       "function F() { };"
    9596             :       "F.prototype = other;"
    9597             :       "var f = new F();")
    9598           6 :       ->Run(current.local())
    9599           6 :       .ToLocalChecked();
    9600             :   v8::Local<Script> access_f0 = v8_compile("f.Object");
    9601             :   v8::Local<Script> access_f1 = v8_compile("f[42]");
    9602          36 :   for (int j = 0; j < 5; j++) {
    9603          60 :     CHECK(access_f0->Run(current.local()).IsEmpty());
    9604          60 :     CHECK(access_f1->Run(current.local()).IsEmpty());
    9605             :   }
    9606             : 
    9607             :   // Now it gets hairy: Set the prototype for the other global object
    9608             :   // to be the current global object. The prototype chain for 'f' now
    9609             :   // goes through 'other' but ends up in the current global object.
    9610             :   { Context::Scope scope(other);
    9611          30 :     CHECK(other->Global()
    9612             :               ->Set(other, v8_str("__proto__"), current->Global())
    9613             :               .FromJust());
    9614             :   }
    9615             :   // Set a named and an index property on the current global
    9616             :   // object. To force the lookup to go through the other global object,
    9617             :   // the properties must not exist in the other global object.
    9618          30 :   CHECK(current->Global()
    9619             :             ->Set(current.local(), v8_str("foo"), v8_num(100))
    9620             :             .FromJust());
    9621          24 :   CHECK(current->Global()
    9622             :             ->Set(current.local(), v8_num(99), v8_num(101))
    9623             :             .FromJust());
    9624             :   // Try to read the properties from f and make sure that the access
    9625             :   // gets stopped by the security checks on the other global object.
    9626             :   Local<Script> access_f2 = v8_compile("f.foo");
    9627             :   Local<Script> access_f3 = v8_compile("f[99]");
    9628          36 :   for (int k = 0; k < 5; k++) {
    9629          60 :     CHECK(access_f2->Run(current.local()).IsEmpty());
    9630          60 :     CHECK(access_f3->Run(current.local()).IsEmpty());
    9631           6 :   }
    9632           6 : }
    9633             : 
    9634             : 
    9635             : static bool security_check_with_gc_called;
    9636             : 
    9637          10 : static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
    9638             :                                        Local<v8::Object> accessed_object,
    9639             :                                        Local<v8::Value> data) {
    9640          10 :   CcTest::CollectAllGarbage();
    9641          10 :   security_check_with_gc_called = true;
    9642          10 :   return true;
    9643             : }
    9644             : 
    9645             : 
    9646       28342 : TEST(SecurityTestGCAllowed) {
    9647           5 :   v8::Isolate* isolate = CcTest::isolate();
    9648           5 :   v8::HandleScope handle_scope(isolate);
    9649             :   v8::Local<v8::ObjectTemplate> object_template =
    9650           5 :       v8::ObjectTemplate::New(isolate);
    9651           5 :   object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
    9652             : 
    9653           5 :   v8::Local<Context> context = Context::New(isolate);
    9654             :   v8::Context::Scope context_scope(context);
    9655             : 
    9656          25 :   CHECK(context->Global()
    9657             :             ->Set(context, v8_str("obj"),
    9658             :                   object_template->NewInstance(context).ToLocalChecked())
    9659             :             .FromJust());
    9660             : 
    9661           5 :   security_check_with_gc_called = false;
    9662             :   CompileRun("obj[0] = new String(1002);");
    9663           5 :   CHECK(security_check_with_gc_called);
    9664             : 
    9665           5 :   security_check_with_gc_called = false;
    9666          20 :   CHECK(CompileRun("obj[0]")
    9667             :             ->ToString(context)
    9668             :             .ToLocalChecked()
    9669             :             ->Equals(context, v8_str("1002"))
    9670             :             .FromJust());
    9671          10 :   CHECK(security_check_with_gc_called);
    9672           5 : }
    9673             : 
    9674             : 
    9675       28343 : THREADED_TEST(CrossDomainDelete) {
    9676           6 :   LocalContext env1;
    9677          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9678           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9679             : 
    9680           6 :   Local<Value> foo = v8_str("foo");
    9681           6 :   Local<Value> bar = v8_str("bar");
    9682             : 
    9683             :   // Set to the same domain.
    9684           6 :   env1->SetSecurityToken(foo);
    9685           6 :   env2->SetSecurityToken(foo);
    9686             : 
    9687          30 :   CHECK(
    9688             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9689          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9690             : 
    9691             :   // Change env2 to a different domain and delete env1.prop.
    9692           6 :   env2->SetSecurityToken(bar);
    9693             :   {
    9694             :     Context::Scope scope_env2(env2);
    9695             :     Local<Value> result =
    9696             :         CompileRun("delete env1.prop");
    9697           6 :     CHECK(result.IsEmpty());
    9698             :   }
    9699             : 
    9700             :   // Check that env1.prop still exists.
    9701             :   Local<Value> v =
    9702          30 :       env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
    9703           6 :   CHECK(v->IsNumber());
    9704          18 :   CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
    9705           6 : }
    9706             : 
    9707             : 
    9708       28343 : THREADED_TEST(CrossDomainPropertyIsEnumerable) {
    9709           6 :   LocalContext env1;
    9710          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9711           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9712             : 
    9713           6 :   Local<Value> foo = v8_str("foo");
    9714           6 :   Local<Value> bar = v8_str("bar");
    9715             : 
    9716             :   // Set to the same domain.
    9717           6 :   env1->SetSecurityToken(foo);
    9718           6 :   env2->SetSecurityToken(foo);
    9719             : 
    9720          30 :   CHECK(
    9721             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9722          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9723             : 
    9724             :   // env1.prop is enumerable in env2.
    9725           6 :   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
    9726             :   {
    9727             :     Context::Scope scope_env2(env2);
    9728           6 :     Local<Value> result = CompileRun(test);
    9729           6 :     CHECK(result->IsTrue());
    9730             :   }
    9731             : 
    9732             :   // Change env2 to a different domain and test again.
    9733           6 :   env2->SetSecurityToken(bar);
    9734             :   {
    9735             :     Context::Scope scope_env2(env2);
    9736           6 :     Local<Value> result = CompileRun(test);
    9737           6 :     CHECK(result.IsEmpty());
    9738           6 :   }
    9739           6 : }
    9740             : 
    9741             : 
    9742       28343 : THREADED_TEST(CrossDomainFor) {
    9743           6 :   LocalContext env1;
    9744          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9745           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9746             : 
    9747           6 :   Local<Value> foo = v8_str("foo");
    9748           6 :   Local<Value> bar = v8_str("bar");
    9749             : 
    9750             :   // Set to the same domain.
    9751           6 :   env1->SetSecurityToken(foo);
    9752           6 :   env2->SetSecurityToken(foo);
    9753             : 
    9754          30 :   CHECK(
    9755             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9756          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9757             : 
    9758             :   // Change env2 to a different domain and set env1's global object
    9759             :   // as the __proto__ of an object in env2 and enumerate properties
    9760             :   // in for-in. It shouldn't enumerate properties on env1's global
    9761             :   // object. It shouldn't throw either, just silently ignore them.
    9762           6 :   env2->SetSecurityToken(bar);
    9763             :   {
    9764             :     Context::Scope scope_env2(env2);
    9765             :     Local<Value> result = CompileRun(
    9766             :         "(function() {"
    9767             :         "  try {"
    9768             :         "    for (var p in env1) {"
    9769             :         "      if (p == 'prop') return false;"
    9770             :         "    }"
    9771             :         "    return true;"
    9772             :         "  } catch (e) {"
    9773             :         "    return false;"
    9774             :         "  }"
    9775             :         "})()");
    9776           6 :     CHECK(result->IsTrue());
    9777           6 :   }
    9778           6 : }
    9779             : 
    9780             : 
    9781       28343 : THREADED_TEST(CrossDomainForInOnPrototype) {
    9782           6 :   LocalContext env1;
    9783          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9784           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9785             : 
    9786           6 :   Local<Value> foo = v8_str("foo");
    9787           6 :   Local<Value> bar = v8_str("bar");
    9788             : 
    9789             :   // Set to the same domain.
    9790           6 :   env1->SetSecurityToken(foo);
    9791           6 :   env2->SetSecurityToken(foo);
    9792             : 
    9793          30 :   CHECK(
    9794             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9795          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9796             : 
    9797             :   // Change env2 to a different domain and set env1's global object
    9798             :   // as the __proto__ of an object in env2 and enumerate properties
    9799             :   // in for-in. It shouldn't enumerate properties on env1's global
    9800             :   // object.
    9801           6 :   env2->SetSecurityToken(bar);
    9802             :   {
    9803             :     Context::Scope scope_env2(env2);
    9804             :     Local<Value> result = CompileRun(
    9805             :         "(function() {"
    9806             :         "  var obj = { '__proto__': env1 };"
    9807             :         "  try {"
    9808             :         "    for (var p in obj) {"
    9809             :         "      if (p == 'prop') return false;"
    9810             :         "    }"
    9811             :         "    return true;"
    9812             :         "  } catch (e) {"
    9813             :         "    return false;"
    9814             :         "  }"
    9815             :         "})()");
    9816           6 :     CHECK(result->IsTrue());
    9817           6 :   }
    9818           6 : }
    9819             : 
    9820             : 
    9821       28342 : TEST(ContextDetachGlobal) {
    9822           5 :   LocalContext env1;
    9823          10 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9824           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9825             : 
    9826             : 
    9827           5 :   Local<Value> foo = v8_str("foo");
    9828             : 
    9829             :   // Set to the same domain.
    9830           5 :   env1->SetSecurityToken(foo);
    9831           5 :   env2->SetSecurityToken(foo);
    9832             : 
    9833             :   // Enter env2
    9834           5 :   env2->Enter();
    9835             : 
    9836             :   // Create a function in env2 and add a reference to it in env1.
    9837           5 :   Local<v8::Object> global2 = env2->Global();
    9838          20 :   CHECK(global2->Set(env2, v8_str("prop"),
    9839             :                      v8::Integer::New(env2->GetIsolate(), 1))
    9840             :             .FromJust());
    9841             :   CompileRun("function getProp() {return prop;}");
    9842             : 
    9843          35 :   CHECK(env1->Global()
    9844             :             ->Set(env1.local(), v8_str("getProp"),
    9845             :                   global2->Get(env2, v8_str("getProp")).ToLocalChecked())
    9846             :             .FromJust());
    9847             : 
    9848             :   // Detach env2's global, and reuse the global object of env2
    9849           5 :   env2->Exit();
    9850           5 :   env2->DetachGlobal();
    9851             : 
    9852             :   v8::Local<Context> env3 = Context::New(
    9853           5 :       env1->GetIsolate(), nullptr, v8::Local<v8::ObjectTemplate>(), global2);
    9854          10 :   env3->SetSecurityToken(v8_str("bar"));
    9855             : 
    9856           5 :   env3->Enter();
    9857           5 :   Local<v8::Object> global3 = env3->Global();
    9858          10 :   CHECK(global2->Equals(env3, global3).FromJust());
    9859          15 :   CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
    9860          15 :   CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
    9861          20 :   CHECK(global3->Set(env3, v8_str("prop"),
    9862             :                      v8::Integer::New(env3->GetIsolate(), -1))
    9863             :             .FromJust());
    9864          20 :   CHECK(global3->Set(env3, v8_str("prop2"),
    9865             :                      v8::Integer::New(env3->GetIsolate(), 2))
    9866             :             .FromJust());
    9867           5 :   env3->Exit();
    9868             : 
    9869             :   // Call getProp in env1, and it should return the value 1
    9870             :   {
    9871           5 :     Local<v8::Object> global1 = env1->Global();
    9872             :     Local<Value> get_prop =
    9873          20 :         global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
    9874           5 :     CHECK(get_prop->IsFunction());
    9875           5 :     v8::TryCatch try_catch(env1->GetIsolate());
    9876             :     Local<Value> r = Function::Cast(*get_prop)
    9877          10 :                          ->Call(env1.local(), global1, 0, nullptr)
    9878           5 :                          .ToLocalChecked();
    9879           5 :     CHECK(!try_catch.HasCaught());
    9880          10 :     CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
    9881             :   }
    9882             : 
    9883             :   // Check that env3 is not accessible from env1
    9884             :   {
    9885          10 :     v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
    9886           5 :     CHECK(r.IsEmpty());
    9887           5 :   }
    9888           5 : }
    9889             : 
    9890             : 
    9891       28342 : TEST(DetachGlobal) {
    9892           5 :   LocalContext env1;
    9893          10 :   v8::HandleScope scope(env1->GetIsolate());
    9894             : 
    9895             :   // Create second environment.
    9896           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9897             : 
    9898           5 :   Local<Value> foo = v8_str("foo");
    9899             : 
    9900             :   // Set same security token for env1 and env2.
    9901           5 :   env1->SetSecurityToken(foo);
    9902           5 :   env2->SetSecurityToken(foo);
    9903             : 
    9904             :   // Create a property on the global object in env2.
    9905             :   {
    9906             :     v8::Context::Scope scope(env2);
    9907          25 :     CHECK(env2->Global()
    9908             :               ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
    9909             :               .FromJust());
    9910             :   }
    9911             : 
    9912             :   // Create a reference to env2 global from env1 global.
    9913          30 :   CHECK(env1->Global()
    9914             :             ->Set(env1.local(), v8_str("other"), env2->Global())
    9915             :             .FromJust());
    9916             : 
    9917             :   // Check that we have access to other.p in env2 from env1.
    9918             :   Local<Value> result = CompileRun("other.p");
    9919           5 :   CHECK(result->IsInt32());
    9920          10 :   CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
    9921             : 
    9922             :   // Hold on to global from env2 and detach global from env2.
    9923           5 :   Local<v8::Object> global2 = env2->Global();
    9924           5 :   env2->DetachGlobal();
    9925             : 
    9926             :   // Check that the global has been detached. No other.p property can
    9927             :   // be found.
    9928             :   result = CompileRun("other.p");
    9929           5 :   CHECK(result.IsEmpty());
    9930             : 
    9931             :   // Reuse global2 for env3.
    9932             :   v8::Local<Context> env3 = Context::New(
    9933           5 :       env1->GetIsolate(), nullptr, v8::Local<v8::ObjectTemplate>(), global2);
    9934          15 :   CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
    9935             : 
    9936             :   // Start by using the same security token for env3 as for env1 and env2.
    9937           5 :   env3->SetSecurityToken(foo);
    9938             : 
    9939             :   // Create a property on the global object in env3.
    9940             :   {
    9941             :     v8::Context::Scope scope(env3);
    9942          25 :     CHECK(env3->Global()
    9943             :               ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
    9944             :               .FromJust());
    9945             :   }
    9946             : 
    9947             :   // Check that other.p is now the property in env3 and that we have access.
    9948             :   result = CompileRun("other.p");
    9949           5 :   CHECK(result->IsInt32());
    9950          15 :   CHECK_EQ(24, result->Int32Value(env3).FromJust());
    9951           5 : }
    9952             : 
    9953             : 
    9954         130 : void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9955          65 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9956             :   info.GetReturnValue().Set(
    9957         260 :       context->Global()->Get(context, v8_str("x")).ToLocalChecked());
    9958          65 : }
    9959             : 
    9960             : 
    9961       28342 : TEST(DetachedAccesses) {
    9962           5 :   LocalContext env1;
    9963          10 :   v8::HandleScope scope(env1->GetIsolate());
    9964             : 
    9965             :   // Create second environment.
    9966             :   Local<ObjectTemplate> inner_global_template =
    9967          10 :       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
    9968             :   inner_global_template ->SetAccessorProperty(
    9969          10 :       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
    9970             :   v8::Local<Context> env2 =
    9971           5 :       Context::New(env1->GetIsolate(), nullptr, inner_global_template);
    9972             : 
    9973           5 :   Local<Value> foo = v8_str("foo");
    9974             : 
    9975             :   // Set same security token for env1 and env2.
    9976           5 :   env1->SetSecurityToken(foo);
    9977           5 :   env2->SetSecurityToken(foo);
    9978             : 
    9979          30 :   CHECK(env1->Global()
    9980             :             ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
    9981             :             .FromJust());
    9982             : 
    9983             :   {
    9984             :     v8::Context::Scope scope(env2);
    9985          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
    9986             :     CompileRun(
    9987             :         "function bound_x() { return x; }"
    9988             :         "function get_x()   { return this.x; }"
    9989             :         "function get_x_w() { return (function() {return this.x;})(); }");
    9990          25 :     CHECK(env1->Global()
    9991             :               ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
    9992             :               .FromJust());
    9993          25 :     CHECK(env1->Global()
    9994             :               ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
    9995             :               .FromJust());
    9996          25 :     CHECK(env1->Global()
    9997             :               ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
    9998             :               .FromJust());
    9999             :     env1->Global()
   10000             :         ->Set(env1.local(), v8_str("this_x"),
   10001          20 :               CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
   10002          10 :         .FromJust();
   10003             :   }
   10004             : 
   10005           5 :   Local<Object> env2_global = env2->Global();
   10006           5 :   env2->DetachGlobal();
   10007             : 
   10008             :   Local<Value> result;
   10009             :   result = CompileRun("bound_x()");
   10010          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   10011             :   result = CompileRun("get_x()");
   10012           5 :   CHECK(result.IsEmpty());
   10013             :   result = CompileRun("get_x_w()");
   10014           5 :   CHECK(result.IsEmpty());
   10015             :   result = CompileRun("this_x()");
   10016          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   10017             : 
   10018             :   // Reattach env2's proxy
   10019             :   env2 = Context::New(env1->GetIsolate(), nullptr,
   10020           5 :                       v8::Local<v8::ObjectTemplate>(), env2_global);
   10021           5 :   env2->SetSecurityToken(foo);
   10022             :   {
   10023             :     v8::Context::Scope scope(env2);
   10024          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
   10025          25 :     CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   10026             :     result = CompileRun(
   10027             :         "results = [];"
   10028             :         "for (var i = 0; i < 4; i++ ) {"
   10029             :         "  results.push(env1.bound_x());"
   10030             :         "  results.push(env1.get_x());"
   10031             :         "  results.push(env1.get_x_w());"
   10032             :         "  results.push(env1.this_x());"
   10033             :         "}"
   10034             :         "results");
   10035             :     Local<v8::Array> results = Local<v8::Array>::Cast(result);
   10036           5 :     CHECK_EQ(16u, results->Length());
   10037          20 :     for (int i = 0; i < 16; i += 4) {
   10038          80 :       CHECK(v8_str("env2_x")
   10039             :                 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
   10040             :                 .FromJust());
   10041          80 :       CHECK(v8_str("env1_x")
   10042             :                 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
   10043             :                 .FromJust());
   10044          80 :       CHECK(v8_str("env3_x")
   10045             :                 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
   10046             :                 .FromJust());
   10047          80 :       CHECK(v8_str("env2_x")
   10048             :                 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
   10049             :                 .FromJust());
   10050             :     }
   10051             :   }
   10052             : 
   10053             :   result = CompileRun(
   10054             :       "results = [];"
   10055             :       "for (var i = 0; i < 4; i++ ) {"
   10056             :       "  results.push(bound_x());"
   10057             :       "  results.push(get_x());"
   10058             :       "  results.push(get_x_w());"
   10059             :       "  results.push(this_x());"
   10060             :       "}"
   10061             :       "results");
   10062             :   Local<v8::Array> results = Local<v8::Array>::Cast(result);
   10063           5 :   CHECK_EQ(16u, results->Length());
   10064          20 :   for (int i = 0; i < 16; i += 4) {
   10065          80 :     CHECK(v8_str("env2_x")
   10066             :               ->Equals(env1.local(),
   10067             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
   10068             :               .FromJust());
   10069          80 :     CHECK(v8_str("env3_x")
   10070             :               ->Equals(env1.local(),
   10071             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
   10072             :               .FromJust());
   10073          80 :     CHECK(v8_str("env3_x")
   10074             :               ->Equals(env1.local(),
   10075             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
   10076             :               .FromJust());
   10077          80 :     CHECK(v8_str("env2_x")
   10078             :               ->Equals(env1.local(),
   10079             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
   10080             :               .FromJust());
   10081             :   }
   10082             : 
   10083             :   result = CompileRun(
   10084             :       "results = [];"
   10085             :       "for (var i = 0; i < 4; i++ ) {"
   10086             :       "  results.push(this.bound_x());"
   10087             :       "  results.push(this.get_x());"
   10088             :       "  results.push(this.get_x_w());"
   10089             :       "  results.push(this.this_x());"
   10090             :       "}"
   10091             :       "results");
   10092             :   results = Local<v8::Array>::Cast(result);
   10093           5 :   CHECK_EQ(16u, results->Length());
   10094          20 :   for (int i = 0; i < 16; i += 4) {
   10095          80 :     CHECK(v8_str("env2_x")
   10096             :               ->Equals(env1.local(),
   10097             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
   10098             :               .FromJust());
   10099          80 :     CHECK(v8_str("env1_x")
   10100             :               ->Equals(env1.local(),
   10101             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
   10102             :               .FromJust());
   10103          80 :     CHECK(v8_str("env3_x")
   10104             :               ->Equals(env1.local(),
   10105             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
   10106             :               .FromJust());
   10107          80 :     CHECK(v8_str("env2_x")
   10108             :               ->Equals(env1.local(),
   10109             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
   10110             :               .FromJust());
   10111           5 :   }
   10112           5 : }
   10113             : 
   10114             : 
   10115             : static bool allowed_access = false;
   10116         370 : static bool AccessBlocker(Local<v8::Context> accessing_context,
   10117             :                           Local<v8::Object> accessed_object,
   10118             :                           Local<v8::Value> data) {
   10119         370 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   10120        1110 :   return context->Global()->Equals(context, accessed_object).FromJust() ||
   10121         370 :          allowed_access;
   10122             : }
   10123             : 
   10124             : 
   10125             : static int g_echo_value = -1;
   10126             : 
   10127             : 
   10128          15 : static void EchoGetter(
   10129             :     Local<String> name,
   10130             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10131          15 :   info.GetReturnValue().Set(v8_num(g_echo_value));
   10132          15 : }
   10133             : 
   10134             : 
   10135          10 : static void EchoSetter(Local<String> name, Local<Value> value,
   10136             :                        const v8::PropertyCallbackInfo<void>& args) {
   10137          10 :   if (value->IsNumber())
   10138             :     g_echo_value =
   10139          20 :         value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   10140          10 : }
   10141             : 
   10142             : 
   10143           0 : static void UnreachableGetter(
   10144             :     Local<String> name,
   10145             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10146           0 :   UNREACHABLE();  // This function should not be called..
   10147             : }
   10148             : 
   10149             : 
   10150           0 : static void UnreachableSetter(Local<String>,
   10151             :                               Local<Value>,
   10152             :                               const v8::PropertyCallbackInfo<void>&) {
   10153           0 :   UNREACHABLE();  // This function should not be called.
   10154             : }
   10155             : 
   10156             : 
   10157           0 : static void UnreachableFunction(
   10158             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   10159           0 :   UNREACHABLE();  // This function should not be called..
   10160             : }
   10161             : 
   10162             : 
   10163       28342 : TEST(AccessControl) {
   10164           5 :   v8::Isolate* isolate = CcTest::isolate();
   10165           5 :   v8::HandleScope handle_scope(isolate);
   10166             :   v8::Local<v8::ObjectTemplate> global_template =
   10167           5 :       v8::ObjectTemplate::New(isolate);
   10168             : 
   10169           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10170             : 
   10171             :   // Add an accessor accessible by cross-domain JS code.
   10172             :   global_template->SetAccessor(
   10173             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10174           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10175             : 
   10176             : 
   10177             :   // Add an accessor that is not accessible by cross-domain JS code.
   10178             :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10179             :                                UnreachableSetter, v8::Local<Value>(),
   10180           5 :                                v8::DEFAULT);
   10181             : 
   10182             :   global_template->SetAccessorProperty(
   10183             :       v8_str("blocked_js_prop"),
   10184             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   10185             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   10186             :       v8::None,
   10187          15 :       v8::DEFAULT);
   10188             : 
   10189             :   // Create an environment
   10190           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10191           5 :   context0->Enter();
   10192             : 
   10193           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10194             : 
   10195             :   // Define a property with JS getter and setter.
   10196             :   CompileRun(
   10197             :       "function getter() { return 'getter'; };\n"
   10198             :       "function setter() { return 'setter'; }\n"
   10199             :       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   10200             : 
   10201             :   Local<Value> getter =
   10202          15 :       global0->Get(context0, v8_str("getter")).ToLocalChecked();
   10203             :   Local<Value> setter =
   10204          15 :       global0->Get(context0, v8_str("setter")).ToLocalChecked();
   10205             : 
   10206             :   // And define normal element.
   10207          15 :   CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
   10208             : 
   10209             :   // Define an element with JS getter and setter.
   10210             :   CompileRun(
   10211             :       "function el_getter() { return 'el_getter'; };\n"
   10212             :       "function el_setter() { return 'el_setter'; };\n"
   10213             :       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   10214             : 
   10215             :   Local<Value> el_getter =
   10216          15 :       global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
   10217             :   Local<Value> el_setter =
   10218          15 :       global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
   10219             : 
   10220          10 :   v8::HandleScope scope1(isolate);
   10221             : 
   10222           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10223           5 :   context1->Enter();
   10224             : 
   10225           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10226          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10227             : 
   10228             :   // Access blocked property.
   10229             :   CompileRun("other.blocked_prop = 1");
   10230             : 
   10231           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10232           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10233             :             .IsEmpty());
   10234           5 :   CHECK(
   10235             :       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
   10236             : 
   10237             :   // Access blocked element.
   10238           5 :   CHECK(CompileRun("other[239] = 1").IsEmpty());
   10239             : 
   10240           5 :   CHECK(CompileRun("other[239]").IsEmpty());
   10241           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
   10242           5 :   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
   10243             : 
   10244           5 :   allowed_access = true;
   10245             :   // Now we can enumerate the property.
   10246             :   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   10247           5 :   allowed_access = false;
   10248             : 
   10249             :   // Access a property with JS accessor.
   10250           5 :   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
   10251             : 
   10252           5 :   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
   10253           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
   10254             :             .IsEmpty());
   10255             : 
   10256           5 :   allowed_access = true;
   10257             : 
   10258           5 :   ExpectString("other.js_accessor_p", "getter");
   10259             :   ExpectObject(
   10260           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   10261             :   ExpectObject(
   10262           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   10263             :   ExpectUndefined(
   10264           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   10265             : 
   10266           5 :   allowed_access = false;
   10267             : 
   10268             :   // Access an element with JS accessor.
   10269           5 :   CHECK(CompileRun("other[42] = 2").IsEmpty());
   10270             : 
   10271           5 :   CHECK(CompileRun("other[42]").IsEmpty());
   10272           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   10273             : 
   10274           5 :   allowed_access = true;
   10275             : 
   10276           5 :   ExpectString("other[42]", "el_getter");
   10277           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   10278           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   10279           5 :   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   10280             : 
   10281           5 :   allowed_access = false;
   10282             : 
   10283             :   v8::Local<Value> value;
   10284             : 
   10285             :   // Access accessible property
   10286             :   value = CompileRun("other.accessible_prop = 3");
   10287           5 :   CHECK(value->IsNumber());
   10288          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10289           5 :   CHECK_EQ(3, g_echo_value);
   10290             : 
   10291             :   value = CompileRun("other.accessible_prop");
   10292           5 :   CHECK(value->IsNumber());
   10293          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10294             : 
   10295             :   value = CompileRun(
   10296             :       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   10297           5 :   CHECK(value->IsNumber());
   10298          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10299             : 
   10300             :   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   10301           5 :   CHECK(value->IsTrue());
   10302             : 
   10303             :   // Enumeration doesn't enumerate accessors from inaccessible objects in
   10304             :   // the prototype chain even if the accessors are in themselves accessible.
   10305             :   // Enumeration doesn't throw, it silently ignores what it can't access.
   10306             :   value = CompileRun(
   10307             :       "(function() {"
   10308             :       "  var obj = { '__proto__': other };"
   10309             :       "  try {"
   10310             :       "    for (var p in obj) {"
   10311             :       "      if (p == 'accessible_prop' ||"
   10312             :       "          p == 'blocked_js_prop' ||"
   10313             :       "          p == 'blocked_js_prop') {"
   10314             :       "        return false;"
   10315             :       "      }"
   10316             :       "    }"
   10317             :       "    return true;"
   10318             :       "  } catch (e) {"
   10319             :       "    return false;"
   10320             :       "  }"
   10321             :       "})()");
   10322           5 :   CHECK(value->IsTrue());
   10323             : 
   10324             :   // Test that preventExtensions fails on a non-accessible object even if that
   10325             :   // object is already non-extensible.
   10326          20 :   CHECK(global1->Set(context1, v8_str("checked_object"),
   10327             :                      global_template->NewInstance(context1).ToLocalChecked())
   10328             :             .FromJust());
   10329           5 :   allowed_access = true;
   10330             :   CompileRun("Object.preventExtensions(checked_object)");
   10331             :   ExpectFalse("Object.isExtensible(checked_object)");
   10332           5 :   allowed_access = false;
   10333           5 :   CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
   10334             : 
   10335           5 :   context1->Exit();
   10336          10 :   context0->Exit();
   10337           5 : }
   10338             : 
   10339             : 
   10340       28342 : TEST(AccessControlES5) {
   10341           5 :   v8::Isolate* isolate = CcTest::isolate();
   10342           5 :   v8::HandleScope handle_scope(isolate);
   10343             :   v8::Local<v8::ObjectTemplate> global_template =
   10344           5 :       v8::ObjectTemplate::New(isolate);
   10345             : 
   10346           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10347             : 
   10348             :   // Add accessible accessor.
   10349             :   global_template->SetAccessor(
   10350             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10351           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10352             : 
   10353             : 
   10354             :   // Add an accessor that is not accessible by cross-domain JS code.
   10355             :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10356             :                                UnreachableSetter, v8::Local<Value>(),
   10357           5 :                                v8::DEFAULT);
   10358             : 
   10359             :   // Create an environment
   10360           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10361           5 :   context0->Enter();
   10362             : 
   10363           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10364             : 
   10365           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10366           5 :   context1->Enter();
   10367           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10368          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10369             : 
   10370             :   // Regression test for issue 1154.
   10371           5 :   CHECK(CompileRun("Object.keys(other).length == 1")->BooleanValue(isolate));
   10372           5 :   CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
   10373             :             ->BooleanValue(isolate));
   10374           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10375             : 
   10376             :   // Regression test for issue 1027.
   10377             :   CompileRun("Object.defineProperty(\n"
   10378             :              "  other, 'blocked_prop', {configurable: false})");
   10379           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10380           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10381             :             .IsEmpty());
   10382             : 
   10383             :   // Regression test for issue 1171.
   10384             :   ExpectTrue("Object.isExtensible(other)");
   10385             :   CompileRun("Object.preventExtensions(other)");
   10386             :   ExpectTrue("Object.isExtensible(other)");
   10387             : 
   10388             :   // Object.seal and Object.freeze.
   10389             :   CompileRun("Object.freeze(other)");
   10390             :   ExpectTrue("Object.isExtensible(other)");
   10391             : 
   10392             :   CompileRun("Object.seal(other)");
   10393             :   ExpectTrue("Object.isExtensible(other)");
   10394             : 
   10395             :   // Regression test for issue 1250.
   10396             :   // Make sure that we can set the accessible accessors value using normal
   10397             :   // assignment.
   10398             :   CompileRun("other.accessible_prop = 42");
   10399           5 :   CHECK_EQ(42, g_echo_value);
   10400             : 
   10401             :   // [[DefineOwnProperty]] always throws for access-checked objects.
   10402           5 :   CHECK(
   10403             :       CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
   10404             :           .IsEmpty());
   10405           5 :   CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
   10406           5 :   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
   10407           5 : }
   10408             : 
   10409         235 : static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
   10410             :                                 Local<v8::Object> global,
   10411             :                                 Local<v8::Value> data) {
   10412         235 :   i::PrintF("Access blocked.\n");
   10413         235 :   return false;
   10414             : }
   10415             : 
   10416           5 : static bool AccessAlwaysAllowed(Local<v8::Context> accessing_context,
   10417             :                                 Local<v8::Object> global,
   10418             :                                 Local<v8::Value> data) {
   10419           5 :   i::PrintF("Access allowed.\n");
   10420           5 :   return true;
   10421             : }
   10422             : 
   10423       28343 : THREADED_TEST(AccessControlGetOwnPropertyNames) {
   10424           6 :   v8::Isolate* isolate = CcTest::isolate();
   10425           6 :   v8::HandleScope handle_scope(isolate);
   10426           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10427             : 
   10428          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10429           6 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10430             : 
   10431             :   // Add an accessor accessible by cross-domain JS code.
   10432             :   obj_template->SetAccessor(
   10433             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10434           6 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10435             : 
   10436             :   // Create an environment
   10437           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   10438           6 :   context0->Enter();
   10439             : 
   10440           6 :   v8::Local<v8::Object> global0 = context0->Global();
   10441             : 
   10442          12 :   v8::HandleScope scope1(CcTest::isolate());
   10443             : 
   10444           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10445           6 :   context1->Enter();
   10446             : 
   10447           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10448          18 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10449          24 :   CHECK(global1->Set(context1, v8_str("object"),
   10450             :                      obj_template->NewInstance(context1).ToLocalChecked())
   10451             :             .FromJust());
   10452             : 
   10453             :   v8::Local<Value> value;
   10454             : 
   10455             :   // Attempt to get the property names of the other global object and
   10456             :   // of an object that requires access checks.  Accessing the other
   10457             :   // global object should be blocked by access checks on the global
   10458             :   // proxy object.  Accessing the object that requires access checks
   10459             :   // is blocked by the access checks on the object itself.
   10460             :   value = CompileRun(
   10461             :       "var names = Object.getOwnPropertyNames(other);"
   10462             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10463           6 :   CHECK(value->BooleanValue(isolate));
   10464             : 
   10465             :   value = CompileRun(
   10466             :       "var names = Object.getOwnPropertyNames(object);"
   10467             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10468           6 :   CHECK(value->BooleanValue(isolate));
   10469             : 
   10470           6 :   context1->Exit();
   10471          12 :   context0->Exit();
   10472           6 : }
   10473             : 
   10474             : 
   10475       28342 : TEST(Regress470113) {
   10476           5 :   v8::Isolate* isolate = CcTest::isolate();
   10477           5 :   v8::HandleScope handle_scope(isolate);
   10478           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10479           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10480          10 :   LocalContext env;
   10481          30 :   CHECK(env->Global()
   10482             :             ->Set(env.local(), v8_str("prohibited"),
   10483             :                   obj_template->NewInstance(env.local()).ToLocalChecked())
   10484             :             .FromJust());
   10485             : 
   10486             :   {
   10487           5 :     v8::TryCatch try_catch(isolate);
   10488             :     CompileRun(
   10489             :         "'use strict';\n"
   10490             :         "class C extends Object {\n"
   10491             :         "   m() { super.powned = 'Powned!'; }\n"
   10492             :         "}\n"
   10493             :         "let c = new C();\n"
   10494             :         "c.m.call(prohibited)");
   10495             : 
   10496           5 :     CHECK(try_catch.HasCaught());
   10497           5 :   }
   10498           5 : }
   10499             : 
   10500             : 
   10501           6 : static void ConstTenGetter(Local<String> name,
   10502             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   10503           6 :   info.GetReturnValue().Set(v8_num(10));
   10504           6 : }
   10505             : 
   10506             : 
   10507       28343 : THREADED_TEST(CrossDomainAccessors) {
   10508           6 :   v8::Isolate* isolate = CcTest::isolate();
   10509           6 :   v8::HandleScope handle_scope(isolate);
   10510             : 
   10511             :   v8::Local<v8::FunctionTemplate> func_template =
   10512           6 :       v8::FunctionTemplate::New(isolate);
   10513             : 
   10514             :   v8::Local<v8::ObjectTemplate> global_template =
   10515           6 :       func_template->InstanceTemplate();
   10516             : 
   10517             :   v8::Local<v8::ObjectTemplate> proto_template =
   10518           6 :       func_template->PrototypeTemplate();
   10519             : 
   10520             :   // Add an accessor to proto that's accessible by cross-domain JS code.
   10521             :   proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, nullptr,
   10522          12 :                               v8::Local<Value>(), v8::ALL_CAN_READ);
   10523             : 
   10524             :   // Add an accessor that is not accessible by cross-domain JS code.
   10525             :   global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter,
   10526          12 :                                nullptr, v8::Local<Value>(), v8::DEFAULT);
   10527             : 
   10528           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10529           6 :   context0->Enter();
   10530             : 
   10531           6 :   Local<v8::Object> global = context0->Global();
   10532             :   // Add a normal property that shadows 'accessible'
   10533          18 :   CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
   10534             : 
   10535             :   // Enter a new context.
   10536          12 :   v8::HandleScope scope1(CcTest::isolate());
   10537           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10538           6 :   context1->Enter();
   10539             : 
   10540           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10541          18 :   CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
   10542             : 
   10543             :   // Should return 10, instead of 11
   10544             :   v8::Local<Value> value =
   10545           6 :       v8_compile("other.accessible")->Run(context1).ToLocalChecked();
   10546           6 :   CHECK(value->IsNumber());
   10547          12 :   CHECK_EQ(10, value->Int32Value(context1).FromJust());
   10548             : 
   10549             :   v8::MaybeLocal<v8::Value> maybe_value =
   10550           6 :       v8_compile("other.unreachable")->Run(context1);
   10551           6 :   CHECK(maybe_value.IsEmpty());
   10552             : 
   10553           6 :   context1->Exit();
   10554          12 :   context0->Exit();
   10555           6 : }
   10556             : 
   10557             : 
   10558             : static int access_count = 0;
   10559             : 
   10560         820 : static bool AccessCounter(Local<v8::Context> accessing_context,
   10561             :                           Local<v8::Object> accessed_object,
   10562             :                           Local<v8::Value> data) {
   10563         820 :   access_count++;
   10564         820 :   return true;
   10565             : }
   10566             : 
   10567             : 
   10568             : // This one is too easily disturbed by other tests.
   10569       28342 : TEST(AccessControlIC) {
   10570           5 :   access_count = 0;
   10571             : 
   10572           5 :   v8::Isolate* isolate = CcTest::isolate();
   10573           5 :   v8::HandleScope handle_scope(isolate);
   10574             : 
   10575             :   // Create an environment.
   10576           5 :   v8::Local<Context> context0 = Context::New(isolate);
   10577           5 :   context0->Enter();
   10578             : 
   10579             :   // Create an object that requires access-check functions to be
   10580             :   // called for cross-domain access.
   10581             :   v8::Local<v8::ObjectTemplate> object_template =
   10582           5 :       v8::ObjectTemplate::New(isolate);
   10583           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   10584             :   Local<v8::Object> object =
   10585           5 :       object_template->NewInstance(context0).ToLocalChecked();
   10586             : 
   10587          10 :   v8::HandleScope scope1(isolate);
   10588             : 
   10589             :   // Create another environment.
   10590           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10591           5 :   context1->Enter();
   10592             : 
   10593             :   // Make easy access to the object from the other environment.
   10594           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10595          15 :   CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
   10596             : 
   10597             :   v8::Local<Value> value;
   10598             : 
   10599             :   // Check that the named access-control function is called every time.
   10600             :   CompileRun("function testProp(obj) {"
   10601             :              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   10602             :              "  for (var j = 0; j < 10; j++) obj.prop;"
   10603             :              "  return obj.prop"
   10604             :              "}");
   10605             :   value = CompileRun("testProp(obj)");
   10606           5 :   CHECK(value->IsNumber());
   10607          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10608           5 :   CHECK_EQ(21, access_count);
   10609             : 
   10610             :   // Check that the named access-control function is called every time.
   10611             :   CompileRun("var p = 'prop';"
   10612             :              "function testKeyed(obj) {"
   10613             :              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   10614             :              "  for (var j = 0; j < 10; j++) obj[p];"
   10615             :              "  return obj[p];"
   10616             :              "}");
   10617             :   // Use obj which requires access checks.  No inline caching is used
   10618             :   // in that case.
   10619             :   value = CompileRun("testKeyed(obj)");
   10620           5 :   CHECK(value->IsNumber());
   10621          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10622           5 :   CHECK_EQ(42, access_count);
   10623             :   // Force the inline caches into generic state and try again.
   10624             :   CompileRun("testKeyed({ a: 0 })");
   10625             :   CompileRun("testKeyed({ b: 0 })");
   10626             :   value = CompileRun("testKeyed(obj)");
   10627           5 :   CHECK(value->IsNumber());
   10628          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10629           5 :   CHECK_EQ(63, access_count);
   10630             : 
   10631             :   // Check that the indexed access-control function is called every time.
   10632           5 :   access_count = 0;
   10633             : 
   10634             :   CompileRun("function testIndexed(obj) {"
   10635             :              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   10636             :              "  for (var j = 0; j < 10; j++) obj[0];"
   10637             :              "  return obj[0]"
   10638             :              "}");
   10639             :   value = CompileRun("testIndexed(obj)");
   10640           5 :   CHECK(value->IsNumber());
   10641          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10642           5 :   CHECK_EQ(21, access_count);
   10643             :   // Force the inline caches into generic state.
   10644             :   CompileRun("testIndexed(new Array(1))");
   10645             :   // Test that the indexed access check is called.
   10646             :   value = CompileRun("testIndexed(obj)");
   10647           5 :   CHECK(value->IsNumber());
   10648          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10649           5 :   CHECK_EQ(42, access_count);
   10650             : 
   10651           5 :   access_count = 0;
   10652             :   // Check that the named access check is called when invoking
   10653             :   // functions on an object that requires access checks.
   10654             :   CompileRun("obj.f = function() {}");
   10655             :   CompileRun("function testCallNormal(obj) {"
   10656             :              "  for (var i = 0; i < 10; i++) obj.f();"
   10657             :              "}");
   10658             :   CompileRun("testCallNormal(obj)");
   10659           5 :   printf("%i\n", access_count);
   10660           5 :   CHECK_EQ(11, access_count);
   10661             : 
   10662             :   // Force obj into slow case.
   10663             :   value = CompileRun("delete obj.prop");
   10664           5 :   CHECK(value->BooleanValue(isolate));
   10665             :   // Force inline caches into dictionary probing mode.
   10666             :   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   10667             :   // Test that the named access check is called.
   10668             :   value = CompileRun("testProp(obj);");
   10669           5 :   CHECK(value->IsNumber());
   10670          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10671           5 :   CHECK_EQ(33, access_count);
   10672             : 
   10673             :   // Force the call inline cache into dictionary probing mode.
   10674             :   CompileRun("o.f = function() {}; testCallNormal(o)");
   10675             :   // Test that the named access check is still called for each
   10676             :   // invocation of the function.
   10677             :   value = CompileRun("testCallNormal(obj)");
   10678           5 :   CHECK_EQ(43, access_count);
   10679             : 
   10680           5 :   context1->Exit();
   10681          10 :   context0->Exit();
   10682           5 : }
   10683             : 
   10684             : 
   10685       28343 : THREADED_TEST(Version) { v8::V8::GetVersion(); }
   10686             : 
   10687             : 
   10688          18 : static void InstanceFunctionCallback(
   10689          18 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10690          18 :   ApiTestFuzzer::Fuzz();
   10691          18 :   args.GetReturnValue().Set(v8_num(12));
   10692          18 : }
   10693             : 
   10694             : 
   10695       28343 : THREADED_TEST(InstanceProperties) {
   10696           6 :   LocalContext context;
   10697           6 :   v8::Isolate* isolate = context->GetIsolate();
   10698          12 :   v8::HandleScope handle_scope(isolate);
   10699             : 
   10700           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10701           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10702             : 
   10703          18 :   instance->Set(v8_str("x"), v8_num(42));
   10704             :   instance->Set(v8_str("f"),
   10705          18 :                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10706             : 
   10707           6 :   Local<Value> o = t->GetFunction(context.local())
   10708           6 :                        .ToLocalChecked()
   10709           6 :                        ->NewInstance(context.local())
   10710             :                        .ToLocalChecked();
   10711             : 
   10712          30 :   CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
   10713             :   Local<Value> value = CompileRun("i.x");
   10714          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10715             : 
   10716             :   value = CompileRun("i.f()");
   10717          18 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10718           6 : }
   10719             : 
   10720             : 
   10721         696 : static void GlobalObjectInstancePropertiesGet(
   10722             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   10723         696 :   ApiTestFuzzer::Fuzz();
   10724         696 : }
   10725             : 
   10726             : 
   10727       28343 : THREADED_TEST(GlobalObjectInstanceProperties) {
   10728           6 :   v8::Isolate* isolate = CcTest::isolate();
   10729           6 :   v8::HandleScope handle_scope(isolate);
   10730             : 
   10731             :   Local<Value> global_object;
   10732             : 
   10733           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10734             :   t->InstanceTemplate()->SetHandler(
   10735          12 :       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   10736           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10737          18 :   instance_template->Set(v8_str("x"), v8_num(42));
   10738             :   instance_template->Set(v8_str("f"),
   10739             :                          v8::FunctionTemplate::New(isolate,
   10740          18 :                                                    InstanceFunctionCallback));
   10741             : 
   10742             :   // The script to check how TurboFan compiles missing global function
   10743             :   // invocations.  function g is not defined and should throw on call.
   10744             :   const char* script =
   10745             :       "function wrapper(call) {"
   10746             :       "  var x = 0, y = 1;"
   10747             :       "  for (var i = 0; i < 1000; i++) {"
   10748             :       "    x += i * 100;"
   10749             :       "    y += i * 100;"
   10750             :       "  }"
   10751             :       "  if (call) g();"
   10752             :       "}"
   10753             :       "for (var i = 0; i < 17; i++) wrapper(false);"
   10754             :       "var thrown = 0;"
   10755             :       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10756             :       "thrown";
   10757             : 
   10758             :   {
   10759           6 :     LocalContext env(nullptr, instance_template);
   10760             :     // Hold on to the global object so it can be used again in another
   10761             :     // environment initialization.
   10762           6 :     global_object = env->Global();
   10763             : 
   10764             :     Local<Value> value = CompileRun("x");
   10765          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10766             :     value = CompileRun("f()");
   10767          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10768             :     value = CompileRun(script);
   10769          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10770             :   }
   10771             : 
   10772             :   {
   10773             :     // Create new environment reusing the global object.
   10774           6 :     LocalContext env(nullptr, instance_template, global_object);
   10775             :     Local<Value> value = CompileRun("x");
   10776          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10777             :     value = CompileRun("f()");
   10778          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10779             :     value = CompileRun(script);
   10780          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10781           6 :   }
   10782           6 : }
   10783             : 
   10784       28343 : THREADED_TEST(ObjectGetOwnPropertyNames) {
   10785           6 :   LocalContext context;
   10786           6 :   v8::Isolate* isolate = context->GetIsolate();
   10787          12 :   v8::HandleScope handle_scope(isolate);
   10788             : 
   10789             :   v8::Local<v8::Object> value = v8::Local<v8::Object>::Cast(
   10790           6 :       v8::StringObject::New(CcTest::isolate(), v8_str("test")));
   10791             :   v8::Local<v8::Array> properties;
   10792             : 
   10793          12 :   CHECK(value
   10794             :             ->GetOwnPropertyNames(context.local(),
   10795             :                                   static_cast<v8::PropertyFilter>(
   10796             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10797             :                                       v8::PropertyFilter::SKIP_SYMBOLS),
   10798             :                                   v8::KeyConversionMode::kKeepNumbers)
   10799             :             .ToLocal(&properties));
   10800           6 :   CHECK_EQ(5u, properties->Length());
   10801             :   v8::Local<v8::Value> property;
   10802          18 :   CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
   10803             :         property->IsString());
   10804          18 :   CHECK(property.As<v8::String>()
   10805             :             ->Equals(context.local(), v8_str("length"))
   10806             :             .FromMaybe(false));
   10807          24 :   for (int i = 0; i < 4; ++i) {
   10808             :     v8::Local<v8::Value> property;
   10809          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10810             :           property->IsInt32());
   10811          24 :     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10812             :   }
   10813             : 
   10814          12 :   CHECK(value
   10815             :             ->GetOwnPropertyNames(context.local(),
   10816             :                                   v8::PropertyFilter::ONLY_ENUMERABLE,
   10817             :                                   v8::KeyConversionMode::kKeepNumbers)
   10818             :             .ToLocal(&properties));
   10819             :   v8::Local<v8::Array> number_properties;
   10820          12 :   CHECK(value
   10821             :             ->GetOwnPropertyNames(context.local(),
   10822             :                                   v8::PropertyFilter::ONLY_ENUMERABLE,
   10823             :                                   v8::KeyConversionMode::kConvertToString)
   10824             :             .ToLocal(&number_properties));
   10825           6 :   CHECK_EQ(4u, properties->Length());
   10826          24 :   for (int i = 0; i < 4; ++i) {
   10827             :     v8::Local<v8::Value> property_index;
   10828             :     v8::Local<v8::Value> property_name;
   10829             : 
   10830          48 :     CHECK(number_properties->Get(context.local(), i).ToLocal(&property_name));
   10831          24 :     CHECK(property_name->IsString());
   10832             : 
   10833          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property_index));
   10834          24 :     CHECK(property_index->IsInt32());
   10835             : 
   10836          24 :     CHECK_EQ(property_index.As<v8::Int32>()->Value(), i);
   10837          48 :     CHECK_EQ(property_name->ToNumber(context.local())
   10838             :                  .ToLocalChecked()
   10839             :                  .As<v8::Int32>()
   10840             :                  ->Value(),
   10841             :              i);
   10842             :   }
   10843             : 
   10844           6 :   value = value->GetPrototype().As<v8::Object>();
   10845          12 :   CHECK(value
   10846             :             ->GetOwnPropertyNames(context.local(),
   10847             :                                   static_cast<v8::PropertyFilter>(
   10848             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10849             :                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10850             :             .ToLocal(&properties));
   10851             :   bool concat_found = false;
   10852             :   bool starts_with_found = false;
   10853         288 :   for (uint32_t i = 0; i < properties->Length(); ++i) {
   10854             :     v8::Local<v8::Value> property;
   10855         576 :     CHECK(properties->Get(context.local(), i).ToLocal(&property));
   10856         288 :     if (!property->IsString()) continue;
   10857         288 :     if (!concat_found)
   10858             :       concat_found = property.As<v8::String>()
   10859         180 :                          ->Equals(context.local(), v8_str("concat"))
   10860         120 :                          .FromMaybe(false);
   10861         288 :     if (!starts_with_found)
   10862             :       starts_with_found = property.As<v8::String>()
   10863         648 :                               ->Equals(context.local(), v8_str("startsWith"))
   10864         432 :                               .FromMaybe(false);
   10865             :   }
   10866          12 :   CHECK(concat_found && starts_with_found);
   10867           6 : }
   10868             : 
   10869       28343 : THREADED_TEST(CallKnownGlobalReceiver) {
   10870           6 :   v8::Isolate* isolate = CcTest::isolate();
   10871           6 :   v8::HandleScope handle_scope(isolate);
   10872             : 
   10873             :   Local<Value> global_object;
   10874             : 
   10875           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10876           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10877             : 
   10878             :   // The script to check that we leave global object not
   10879             :   // global object proxy on stack when we deoptimize from inside
   10880             :   // arguments evaluation.
   10881             :   // To provoke error we need to both force deoptimization
   10882             :   // from arguments evaluation and to force CallIC to take
   10883             :   // CallIC_Miss code path that can't cope with global proxy.
   10884             :   const char* script =
   10885             :       "function bar(x, y) { try { } finally { } }"
   10886             :       "function baz(x) { try { } finally { } }"
   10887             :       "function bom(x) { try { } finally { } }"
   10888             :       "function foo(x) { bar([x], bom(2)); }"
   10889             :       "for (var i = 0; i < 10000; i++) foo(1);"
   10890             :       "foo";
   10891             : 
   10892             :   Local<Value> foo;
   10893             :   {
   10894           6 :     LocalContext env(nullptr, instance_template);
   10895             :     // Hold on to the global object so it can be used again in another
   10896             :     // environment initialization.
   10897           6 :     global_object = env->Global();
   10898           6 :     foo = CompileRun(script);
   10899             :   }
   10900             : 
   10901             :   {
   10902             :     // Create new environment reusing the global object.
   10903           6 :     LocalContext env(nullptr, instance_template, global_object);
   10904          30 :     CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
   10905           6 :     CompileRun("foo()");
   10906           6 :   }
   10907           6 : }
   10908             : 
   10909             : 
   10910           6 : static void ShadowFunctionCallback(
   10911           6 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10912           6 :   ApiTestFuzzer::Fuzz();
   10913           6 :   args.GetReturnValue().Set(v8_num(42));
   10914           6 : }
   10915             : 
   10916             : 
   10917             : static int shadow_y;
   10918             : static int shadow_y_setter_call_count;
   10919             : static int shadow_y_getter_call_count;
   10920             : 
   10921             : 
   10922           6 : static void ShadowYSetter(Local<String>,
   10923             :                           Local<Value>,
   10924             :                           const v8::PropertyCallbackInfo<void>&) {
   10925           6 :   shadow_y_setter_call_count++;
   10926           6 :   shadow_y = 42;
   10927           6 : }
   10928             : 
   10929             : 
   10930           6 : static void ShadowYGetter(Local<String> name,
   10931             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10932           6 :   ApiTestFuzzer::Fuzz();
   10933           6 :   shadow_y_getter_call_count++;
   10934           6 :   info.GetReturnValue().Set(v8_num(shadow_y));
   10935           6 : }
   10936             : 
   10937             : 
   10938           0 : static void ShadowIndexedGet(uint32_t index,
   10939             :                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10940           0 : }
   10941             : 
   10942             : 
   10943          30 : static void ShadowNamedGet(Local<Name> key,
   10944          30 :                            const v8::PropertyCallbackInfo<v8::Value>&) {}
   10945             : 
   10946             : 
   10947       28343 : THREADED_TEST(ShadowObject) {
   10948           6 :   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10949           6 :   v8::Isolate* isolate = CcTest::isolate();
   10950           6 :   v8::HandleScope handle_scope(isolate);
   10951             : 
   10952           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10953          12 :   LocalContext context(nullptr, global_template);
   10954             : 
   10955           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10956             :   t->InstanceTemplate()->SetHandler(
   10957          12 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   10958             :   t->InstanceTemplate()->SetHandler(
   10959          12 :       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   10960           6 :   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10961           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10962             : 
   10963             :   proto->Set(v8_str("f"),
   10964             :              v8::FunctionTemplate::New(isolate,
   10965             :                                        ShadowFunctionCallback,
   10966          18 :                                        Local<Value>()));
   10967          18 :   proto->Set(v8_str("x"), v8_num(12));
   10968             : 
   10969          12 :   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   10970             : 
   10971           6 :   Local<Value> o = t->GetFunction(context.local())
   10972           6 :                        .ToLocalChecked()
   10973           6 :                        ->NewInstance(context.local())
   10974             :                        .ToLocalChecked();
   10975          30 :   CHECK(context->Global()
   10976             :             ->Set(context.local(), v8_str("__proto__"), o)
   10977             :             .FromJust());
   10978             : 
   10979             :   Local<Value> value =
   10980             :       CompileRun("this.propertyIsEnumerable(0)");
   10981           6 :   CHECK(value->IsBoolean());
   10982           6 :   CHECK(!value->BooleanValue(isolate));
   10983             : 
   10984             :   value = CompileRun("x");
   10985          12 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10986             : 
   10987             :   value = CompileRun("f()");
   10988          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10989             : 
   10990             :   CompileRun("y = 43");
   10991           6 :   CHECK_EQ(1, shadow_y_setter_call_count);
   10992             :   value = CompileRun("y");
   10993           6 :   CHECK_EQ(1, shadow_y_getter_call_count);
   10994          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10995           6 : }
   10996             : 
   10997             : 
   10998       28343 : THREADED_TEST(HiddenPrototype) {
   10999           6 :   LocalContext context;
   11000           6 :   v8::Isolate* isolate = context->GetIsolate();
   11001          12 :   v8::HandleScope handle_scope(isolate);
   11002             : 
   11003           6 :   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   11004          24 :   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   11005           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11006           6 :   t1->SetHiddenPrototype(true);
   11007          24 :   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   11008           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11009           6 :   t2->SetHiddenPrototype(true);
   11010          24 :   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   11011           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11012          24 :   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   11013             : 
   11014           6 :   Local<v8::Object> o0 = t0->GetFunction(context.local())
   11015           6 :                              .ToLocalChecked()
   11016           6 :                              ->NewInstance(context.local())
   11017             :                              .ToLocalChecked();
   11018           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11019           6 :                              .ToLocalChecked()
   11020           6 :                              ->NewInstance(context.local())
   11021             :                              .ToLocalChecked();
   11022           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11023           6 :                              .ToLocalChecked()
   11024           6 :                              ->NewInstance(context.local())
   11025             :                              .ToLocalChecked();
   11026           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11027           6 :                              .ToLocalChecked()
   11028           6 :                              ->NewInstance(context.local())
   11029             :                              .ToLocalChecked();
   11030             : 
   11031             :   // Setting the prototype on an object skips hidden prototypes.
   11032          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11033             :                   .ToLocalChecked()
   11034             :                   ->Int32Value(context.local())
   11035             :                   .FromJust());
   11036          18 :   CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
   11037          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11038             :                   .ToLocalChecked()
   11039             :                   ->Int32Value(context.local())
   11040             :                   .FromJust());
   11041          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11042             :                   .ToLocalChecked()
   11043             :                   ->Int32Value(context.local())
   11044             :                   .FromJust());
   11045          18 :   CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
   11046          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11047             :                   .ToLocalChecked()
   11048             :                   ->Int32Value(context.local())
   11049             :                   .FromJust());
   11050          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11051             :                   .ToLocalChecked()
   11052             :                   ->Int32Value(context.local())
   11053             :                   .FromJust());
   11054          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11055             :                   .ToLocalChecked()
   11056             :                   ->Int32Value(context.local())
   11057             :                   .FromJust());
   11058          18 :   CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
   11059          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11060             :                   .ToLocalChecked()
   11061             :                   ->Int32Value(context.local())
   11062             :                   .FromJust());
   11063          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11064             :                   .ToLocalChecked()
   11065             :                   ->Int32Value(context.local())
   11066             :                   .FromJust());
   11067          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11068             :                   .ToLocalChecked()
   11069             :                   ->Int32Value(context.local())
   11070             :                   .FromJust());
   11071          24 :   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   11072             :                   .ToLocalChecked()
   11073             :                   ->Int32Value(context.local())
   11074             :                   .FromJust());
   11075             : 
   11076             :   // Getting the prototype of o0 should get the first visible one
   11077             :   // which is o3.  Therefore, z should not be defined on the prototype
   11078             :   // object.
   11079             :   Local<Value> proto =
   11080          18 :       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   11081           6 :   CHECK(proto->IsObject());
   11082          18 :   CHECK(proto.As<v8::Object>()
   11083             :             ->Get(context.local(), v8_str("z"))
   11084             :             .ToLocalChecked()
   11085           6 :             ->IsUndefined());
   11086           6 : }
   11087             : 
   11088             : 
   11089       28343 : THREADED_TEST(HiddenPrototypeSet) {
   11090           6 :   LocalContext context;
   11091           6 :   v8::Isolate* isolate = context->GetIsolate();
   11092          12 :   v8::HandleScope handle_scope(isolate);
   11093             : 
   11094           6 :   Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
   11095           6 :   Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
   11096           6 :   ht->SetHiddenPrototype(true);
   11097           6 :   Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
   11098          24 :   ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   11099             : 
   11100           6 :   Local<v8::Object> o = ot->GetFunction(context.local())
   11101           6 :                             .ToLocalChecked()
   11102           6 :                             ->NewInstance(context.local())
   11103             :                             .ToLocalChecked();
   11104           6 :   Local<v8::Object> h = ht->GetFunction(context.local())
   11105           6 :                             .ToLocalChecked()
   11106           6 :                             ->NewInstance(context.local())
   11107             :                             .ToLocalChecked();
   11108           6 :   Local<v8::Object> p = pt->GetFunction(context.local())
   11109           6 :                             .ToLocalChecked()
   11110           6 :                             ->NewInstance(context.local())
   11111             :                             .ToLocalChecked();
   11112          18 :   CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
   11113          18 :   CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
   11114             : 
   11115             :   // Setting a property that exists on the hidden prototype goes there.
   11116          18 :   CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
   11117          24 :   CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
   11118             :                   .ToLocalChecked()
   11119             :                   ->Int32Value(context.local())
   11120             :                   .FromJust());
   11121          24 :   CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
   11122             :                   .ToLocalChecked()
   11123             :                   ->Int32Value(context.local())
   11124             :                   .FromJust());
   11125          18 :   CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
   11126             : 
   11127             :   // Setting a new property should not be forwarded to the hidden prototype.
   11128          18 :   CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
   11129          24 :   CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
   11130             :                   .ToLocalChecked()
   11131             :                   ->Int32Value(context.local())
   11132             :                   .FromJust());
   11133          18 :   CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   11134          18 :   CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
   11135             : 
   11136             :   // Setting a property that only exists on a prototype of the hidden prototype
   11137             :   // is treated normally again.
   11138          18 :   CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
   11139          24 :   CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
   11140             :                   .ToLocalChecked()
   11141             :                   ->Int32Value(context.local())
   11142             :                   .FromJust());
   11143          24 :   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   11144             :                   .ToLocalChecked()
   11145             :                   ->Int32Value(context.local())
   11146             :                   .FromJust());
   11147          24 :   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   11148             :                   .ToLocalChecked()
   11149             :                   ->Int32Value(context.local())
   11150             :                   .FromJust());
   11151          18 :   CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
   11152          24 :   CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
   11153             :                   .ToLocalChecked()
   11154             :                   ->Int32Value(context.local())
   11155             :                   .FromJust());
   11156          24 :   CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
   11157             :                   .ToLocalChecked()
   11158             :                   ->Int32Value(context.local())
   11159             :                   .FromJust());
   11160          24 :   CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
   11161             :                   .ToLocalChecked()
   11162             :                   ->Int32Value(context.local())
   11163           6 :                   .FromJust());
   11164           6 : }
   11165             : 
   11166             : 
   11167             : // Regression test for issue 2457.
   11168       28343 : THREADED_TEST(HiddenPrototypeIdentityHash) {
   11169           6 :   LocalContext context;
   11170          12 :   v8::HandleScope handle_scope(context->GetIsolate());
   11171             : 
   11172           6 :   Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
   11173           6 :   t->SetHiddenPrototype(true);
   11174          24 :   t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
   11175           6 :   Local<Object> p = t->GetFunction(context.local())
   11176           6 :                         .ToLocalChecked()
   11177           6 :                         ->NewInstance(context.local())
   11178             :                         .ToLocalChecked();
   11179           6 :   Local<Object> o = Object::New(context->GetIsolate());
   11180          12 :   CHECK(o->SetPrototype(context.local(), p).FromJust());
   11181             : 
   11182           6 :   int hash = o->GetIdentityHash();
   11183             :   USE(hash);
   11184          18 :   CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
   11185          12 :   CHECK_EQ(hash, o->GetIdentityHash());
   11186           6 : }
   11187             : 
   11188             : 
   11189       28343 : THREADED_TEST(SetPrototype) {
   11190           6 :   LocalContext context;
   11191           6 :   v8::Isolate* isolate = context->GetIsolate();
   11192          12 :   v8::HandleScope handle_scope(isolate);
   11193             : 
   11194           6 :   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   11195          24 :   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   11196           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11197           6 :   t1->SetHiddenPrototype(true);
   11198          24 :   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   11199           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11200           6 :   t2->SetHiddenPrototype(true);
   11201          24 :   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   11202           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11203          24 :   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   11204             : 
   11205           6 :   Local<v8::Object> o0 = t0->GetFunction(context.local())
   11206           6 :                              .ToLocalChecked()
   11207           6 :                              ->NewInstance(context.local())
   11208             :                              .ToLocalChecked();
   11209           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11210           6 :                              .ToLocalChecked()
   11211           6 :                              ->NewInstance(context.local())
   11212             :                              .ToLocalChecked();
   11213           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11214           6 :                              .ToLocalChecked()
   11215           6 :                              ->NewInstance(context.local())
   11216             :                              .ToLocalChecked();
   11217           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11218           6 :                              .ToLocalChecked()
   11219           6 :                              ->NewInstance(context.local())
   11220             :                              .ToLocalChecked();
   11221             : 
   11222             :   // Setting the prototype on an object does not skip hidden prototypes.
   11223          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11224             :                   .ToLocalChecked()
   11225             :                   ->Int32Value(context.local())
   11226             :                   .FromJust());
   11227          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11228          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11229             :                   .ToLocalChecked()
   11230             :                   ->Int32Value(context.local())
   11231             :                   .FromJust());
   11232          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11233             :                   .ToLocalChecked()
   11234             :                   ->Int32Value(context.local())
   11235             :                   .FromJust());
   11236          12 :   CHECK(o1->SetPrototype(context.local(), o2).FromJust());
   11237          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11238             :                   .ToLocalChecked()
   11239             :                   ->Int32Value(context.local())
   11240             :                   .FromJust());
   11241          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11242             :                   .ToLocalChecked()
   11243             :                   ->Int32Value(context.local())
   11244             :                   .FromJust());
   11245          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11246             :                   .ToLocalChecked()
   11247             :                   ->Int32Value(context.local())
   11248             :                   .FromJust());
   11249          12 :   CHECK(o2->SetPrototype(context.local(), o3).FromJust());
   11250          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11251             :                   .ToLocalChecked()
   11252             :                   ->Int32Value(context.local())
   11253             :                   .FromJust());
   11254          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11255             :                   .ToLocalChecked()
   11256             :                   ->Int32Value(context.local())
   11257             :                   .FromJust());
   11258          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11259             :                   .ToLocalChecked()
   11260             :                   ->Int32Value(context.local())
   11261             :                   .FromJust());
   11262          24 :   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   11263             :                   .ToLocalChecked()
   11264             :                   ->Int32Value(context.local())
   11265             :                   .FromJust());
   11266             : 
   11267             :   // Getting the prototype of o0 should get the first visible one
   11268             :   // which is o3.  Therefore, z should not be defined on the prototype
   11269             :   // object.
   11270             :   Local<Value> proto =
   11271          18 :       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   11272           6 :   CHECK(proto->IsObject());
   11273          12 :   CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   11274             : 
   11275             :   // However, Object::GetPrototype ignores hidden prototype.
   11276           6 :   Local<Value> proto0 = o0->GetPrototype();
   11277           6 :   CHECK(proto0->IsObject());
   11278          12 :   CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   11279             : 
   11280           6 :   Local<Value> proto1 = o1->GetPrototype();
   11281           6 :   CHECK(proto1->IsObject());
   11282          12 :   CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
   11283             : 
   11284           6 :   Local<Value> proto2 = o2->GetPrototype();
   11285           6 :   CHECK(proto2->IsObject());
   11286          18 :   CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   11287           6 : }
   11288             : 
   11289             : 
   11290             : // Getting property names of an object with a prototype chain that
   11291             : // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   11292             : // crash the runtime.
   11293       28343 : THREADED_TEST(Regress91517) {
   11294           6 :   i::FLAG_allow_natives_syntax = true;
   11295           6 :   LocalContext context;
   11296           6 :   v8::Isolate* isolate = context->GetIsolate();
   11297          12 :   v8::HandleScope handle_scope(isolate);
   11298             : 
   11299           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11300           6 :   t1->SetHiddenPrototype(true);
   11301          24 :   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   11302           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11303           6 :   t2->SetHiddenPrototype(true);
   11304          24 :   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   11305          12 :   t2->InstanceTemplate()->Set(v8_str("objects"),
   11306          24 :                               v8::ObjectTemplate::New(isolate));
   11307          24 :   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   11308           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11309           6 :   t3->SetHiddenPrototype(true);
   11310          24 :   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   11311           6 :   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   11312          24 :   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   11313             : 
   11314             :   // Force dictionary-based properties.
   11315             :   i::ScopedVector<char> name_buf(1024);
   11316        6006 :   for (int i = 1; i <= 1000; i++) {
   11317        6000 :     i::SNPrintF(name_buf, "sdf%d", i);
   11318       24000 :     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   11319             :   }
   11320             : 
   11321           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11322           6 :                              .ToLocalChecked()
   11323           6 :                              ->NewInstance(context.local())
   11324             :                              .ToLocalChecked();
   11325           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11326           6 :                              .ToLocalChecked()
   11327           6 :                              ->NewInstance(context.local())
   11328             :                              .ToLocalChecked();
   11329           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11330           6 :                              .ToLocalChecked()
   11331           6 :                              ->NewInstance(context.local())
   11332             :                              .ToLocalChecked();
   11333           6 :   Local<v8::Object> o4 = t4->GetFunction(context.local())
   11334           6 :                              .ToLocalChecked()
   11335           6 :                              ->NewInstance(context.local())
   11336             :                              .ToLocalChecked();
   11337             : 
   11338             :   // Create prototype chain of hidden prototypes.
   11339          12 :   CHECK(o4->SetPrototype(context.local(), o3).FromJust());
   11340          12 :   CHECK(o3->SetPrototype(context.local(), o2).FromJust());
   11341          12 :   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11342             : 
   11343             :   // Call the runtime version of GetOwnPropertyNames() on the natively
   11344             :   // created object through JavaScript.
   11345          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
   11346             :   // PROPERTY_FILTER_NONE = 0
   11347             :   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11348             : 
   11349           6 :   ExpectInt32("names.length", 1006);
   11350             :   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11351             :   ExpectTrue("names.indexOf(\"boo\") >= 0");
   11352             :   ExpectTrue("names.indexOf(\"foo\") >= 0");
   11353             :   ExpectTrue("names.indexOf(\"fuz1\") >= 0");
   11354             :   ExpectTrue("names.indexOf(\"objects\") >= 0");
   11355             :   ExpectTrue("names.indexOf(\"fuz2\") >= 0");
   11356           6 :   ExpectFalse("names[1005] == undefined");
   11357           6 : }
   11358             : 
   11359             : 
   11360             : // Getting property names of an object with a hidden and inherited
   11361             : // prototype should not duplicate the accessor properties inherited.
   11362       28343 : THREADED_TEST(Regress269562) {
   11363           6 :   i::FLAG_allow_natives_syntax = true;
   11364           6 :   LocalContext context;
   11365          12 :   v8::HandleScope handle_scope(context->GetIsolate());
   11366             : 
   11367             :   Local<v8::FunctionTemplate> t1 =
   11368           6 :       v8::FunctionTemplate::New(context->GetIsolate());
   11369           6 :   t1->SetHiddenPrototype(true);
   11370             : 
   11371           6 :   Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
   11372             :   i1->SetAccessor(v8_str("foo"),
   11373           6 :                   SimpleAccessorGetter, SimpleAccessorSetter);
   11374             :   i1->SetAccessor(v8_str("bar"),
   11375           6 :                   SimpleAccessorGetter, SimpleAccessorSetter);
   11376             :   i1->SetAccessor(v8_str("baz"),
   11377           6 :                   SimpleAccessorGetter, SimpleAccessorSetter);
   11378          18 :   i1->Set(v8_str("n1"), v8_num(1));
   11379          18 :   i1->Set(v8_str("n2"), v8_num(2));
   11380             : 
   11381           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11382           6 :                              .ToLocalChecked()
   11383           6 :                              ->NewInstance(context.local())
   11384             :                              .ToLocalChecked();
   11385             :   Local<v8::FunctionTemplate> t2 =
   11386           6 :       v8::FunctionTemplate::New(context->GetIsolate());
   11387           6 :   t2->SetHiddenPrototype(true);
   11388             : 
   11389             :   // Inherit from t1 and mark prototype as hidden.
   11390           6 :   t2->Inherit(t1);
   11391          24 :   t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
   11392             : 
   11393           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11394           6 :                              .ToLocalChecked()
   11395           6 :                              ->NewInstance(context.local())
   11396             :                              .ToLocalChecked();
   11397          12 :   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11398             : 
   11399             :   v8::Local<v8::Symbol> sym =
   11400          12 :       v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
   11401          18 :   CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
   11402             :   o1->SetPrivate(context.local(),
   11403             :                  v8::Private::New(context->GetIsolate(), v8_str("h1")),
   11404          24 :                  v8::Integer::New(context->GetIsolate(), 2013))
   11405          12 :       .FromJust();
   11406             : 
   11407             :   // Call the runtime version of GetOwnPropertyNames() on
   11408             :   // the natively created object through JavaScript.
   11409          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
   11410          30 :   CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
   11411             :   // PROPERTY_FILTER_NONE = 0
   11412             :   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11413             : 
   11414           6 :   ExpectInt32("names.length", 7);
   11415             :   ExpectTrue("names.indexOf(\"foo\") >= 0");
   11416             :   ExpectTrue("names.indexOf(\"bar\") >= 0");
   11417             :   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11418             :   ExpectTrue("names.indexOf(\"n1\") >= 0");
   11419             :   ExpectTrue("names.indexOf(\"n2\") >= 0");
   11420             :   ExpectTrue("names.indexOf(sym) >= 0");
   11421           6 :   ExpectTrue("names.indexOf(\"mine\") >= 0");
   11422           6 : }
   11423             : 
   11424             : 
   11425       28343 : THREADED_TEST(FunctionReadOnlyPrototype) {
   11426           6 :   LocalContext context;
   11427           6 :   v8::Isolate* isolate = context->GetIsolate();
   11428          12 :   v8::HandleScope handle_scope(isolate);
   11429             : 
   11430           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11431          24 :   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11432           6 :   t1->ReadOnlyPrototype();
   11433          36 :   CHECK(context->Global()
   11434             :             ->Set(context.local(), v8_str("func1"),
   11435             :                   t1->GetFunction(context.local()).ToLocalChecked())
   11436             :             .FromJust());
   11437             :   // Configured value of ReadOnly flag.
   11438           6 :   CHECK(
   11439             :       CompileRun(
   11440             :           "(function() {"
   11441             :           "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   11442             :           "  return (descriptor['writable'] == false);"
   11443             :           "})()")
   11444             :           ->BooleanValue(isolate));
   11445          18 :   CHECK_EQ(
   11446             :       42,
   11447             :       CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
   11448          18 :   CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
   11449             :                    ->Int32Value(context.local())
   11450             :                    .FromJust());
   11451             : 
   11452           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11453          24 :   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11454          36 :   CHECK(context->Global()
   11455             :             ->Set(context.local(), v8_str("func2"),
   11456             :                   t2->GetFunction(context.local()).ToLocalChecked())
   11457             :             .FromJust());
   11458             :   // Default value of ReadOnly flag.
   11459           6 :   CHECK(
   11460             :       CompileRun(
   11461             :           "(function() {"
   11462             :           "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   11463             :           "  return (descriptor['writable'] == true);"
   11464             :           "})()")
   11465             :           ->BooleanValue(isolate));
   11466          18 :   CHECK_EQ(
   11467             :       42,
   11468           6 :       CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
   11469           6 : }
   11470             : 
   11471             : 
   11472       28343 : THREADED_TEST(SetPrototypeThrows) {
   11473           6 :   LocalContext context;
   11474           6 :   v8::Isolate* isolate = context->GetIsolate();
   11475          12 :   v8::HandleScope handle_scope(isolate);
   11476             : 
   11477           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11478             : 
   11479           6 :   Local<v8::Object> o0 = t->GetFunction(context.local())
   11480           6 :                              .ToLocalChecked()
   11481           6 :                              ->NewInstance(context.local())
   11482             :                              .ToLocalChecked();
   11483           6 :   Local<v8::Object> o1 = t->GetFunction(context.local())
   11484           6 :                              .ToLocalChecked()
   11485           6 :                              ->NewInstance(context.local())
   11486             :                              .ToLocalChecked();
   11487             : 
   11488          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11489             :   // If setting the prototype leads to the cycle, SetPrototype should
   11490             :   // return false and keep VM in sane state.
   11491          12 :   v8::TryCatch try_catch(isolate);
   11492          12 :   CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
   11493           6 :   CHECK(!try_catch.HasCaught());
   11494           6 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   11495             : 
   11496          18 :   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
   11497             :                    ->Int32Value(context.local())
   11498           6 :                    .FromJust());
   11499           6 : }
   11500             : 
   11501             : 
   11502       28343 : THREADED_TEST(FunctionRemovePrototype) {
   11503           6 :   LocalContext context;
   11504           6 :   v8::Isolate* isolate = context->GetIsolate();
   11505          12 :   v8::HandleScope handle_scope(isolate);
   11506             : 
   11507           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11508           6 :   t1->RemovePrototype();
   11509           6 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   11510           6 :   CHECK(!fun->IsConstructor());
   11511          30 :   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   11512           6 :   CHECK(!CompileRun("'prototype' in fun")->BooleanValue(isolate));
   11513             : 
   11514          12 :   v8::TryCatch try_catch(isolate);
   11515             :   CompileRun("new fun()");
   11516           6 :   CHECK(try_catch.HasCaught());
   11517             : 
   11518           6 :   try_catch.Reset();
   11519          12 :   CHECK(fun->NewInstance(context.local()).IsEmpty());
   11520          12 :   CHECK(try_catch.HasCaught());
   11521           6 : }
   11522             : 
   11523             : 
   11524       28343 : THREADED_TEST(GetterSetterExceptions) {
   11525           6 :   LocalContext context;
   11526           6 :   v8::Isolate* isolate = context->GetIsolate();
   11527          12 :   v8::HandleScope handle_scope(isolate);
   11528             :   CompileRun(
   11529             :       "function Foo() { };"
   11530             :       "function Throw() { throw 5; };"
   11531             :       "var x = { };"
   11532             :       "x.__defineSetter__('set', Throw);"
   11533             :       "x.__defineGetter__('get', Throw);");
   11534             :   Local<v8::Object> x = Local<v8::Object>::Cast(
   11535          30 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
   11536          12 :   v8::TryCatch try_catch(isolate);
   11537          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11538             :             .IsNothing());
   11539          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11540          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11541             :             .IsNothing());
   11542          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11543          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11544             :             .IsNothing());
   11545          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11546          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11547             :             .IsNothing());
   11548          24 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11549           6 : }
   11550             : 
   11551             : 
   11552       28343 : THREADED_TEST(Constructor) {
   11553           6 :   LocalContext context;
   11554           6 :   v8::Isolate* isolate = context->GetIsolate();
   11555          12 :   v8::HandleScope handle_scope(isolate);
   11556           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11557           6 :   templ->SetClassName(v8_str("Fun"));
   11558           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11559          30 :   CHECK(
   11560             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11561           6 :   Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
   11562             :   i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
   11563          12 :   CHECK(obj->IsJSObject());
   11564             :   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   11565          12 :   CHECK(value->BooleanValue(isolate));
   11566           6 : }
   11567             : 
   11568             : 
   11569       28343 : THREADED_TEST(FunctionDescriptorException) {
   11570           6 :   LocalContext context;
   11571           6 :   v8::Isolate* isolate = context->GetIsolate();
   11572          12 :   v8::HandleScope handle_scope(isolate);
   11573           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11574           6 :   templ->SetClassName(v8_str("Fun"));
   11575           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11576          30 :   CHECK(
   11577             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11578             :   Local<Value> value = CompileRun(
   11579             :       "function test() {"
   11580             :       "  try {"
   11581             :       "    (new Fun()).blah()"
   11582             :       "  } catch (e) {"
   11583             :       "    var str = String(e);"
   11584             :       // "    if (str.indexOf('TypeError') == -1) return 1;"
   11585             :       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   11586             :       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   11587             :       "    return 0;"
   11588             :       "  }"
   11589             :       "  return 4;"
   11590             :       "}"
   11591             :       "test();");
   11592          18 :   CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
   11593           6 : }
   11594             : 
   11595             : 
   11596       28343 : THREADED_TEST(EvalAliasedDynamic) {
   11597           6 :   LocalContext current;
   11598          12 :   v8::HandleScope scope(current->GetIsolate());
   11599             : 
   11600             :   // Tests where aliased eval can only be resolved dynamically.
   11601             :   Local<Script> script = v8_compile(
   11602             :       "function f(x) { "
   11603             :       "  var foo = 2;"
   11604             :       "  with (x) { return eval('foo'); }"
   11605             :       "}"
   11606             :       "foo = 0;"
   11607             :       "result1 = f(new Object());"
   11608             :       "result2 = f(this);"
   11609             :       "var x = new Object();"
   11610             :       "x.eval = function(x) { return 1; };"
   11611             :       "result3 = f(x);");
   11612           6 :   script->Run(current.local()).ToLocalChecked();
   11613          36 :   CHECK_EQ(2, current->Global()
   11614             :                   ->Get(current.local(), v8_str("result1"))
   11615             :                   .ToLocalChecked()
   11616             :                   ->Int32Value(current.local())
   11617             :                   .FromJust());
   11618          36 :   CHECK_EQ(0, current->Global()
   11619             :                   ->Get(current.local(), v8_str("result2"))
   11620             :                   .ToLocalChecked()
   11621             :                   ->Int32Value(current.local())
   11622             :                   .FromJust());
   11623          36 :   CHECK_EQ(1, current->Global()
   11624             :                   ->Get(current.local(), v8_str("result3"))
   11625             :                   .ToLocalChecked()
   11626             :                   ->Int32Value(current.local())
   11627             :                   .FromJust());
   11628             : 
   11629          12 :   v8::TryCatch try_catch(current->GetIsolate());
   11630             :   script = v8_compile(
   11631             :       "function f(x) { "
   11632             :       "  var bar = 2;"
   11633             :       "  with (x) { return eval('bar'); }"
   11634             :       "}"
   11635             :       "result4 = f(this)");
   11636           6 :   script->Run(current.local()).ToLocalChecked();
   11637           6 :   CHECK(!try_catch.HasCaught());
   11638          36 :   CHECK_EQ(2, current->Global()
   11639             :                   ->Get(current.local(), v8_str("result4"))
   11640             :                   .ToLocalChecked()
   11641             :                   ->Int32Value(current.local())
   11642             :                   .FromJust());
   11643             : 
   11644          12 :   try_catch.Reset();
   11645           6 : }
   11646             : 
   11647             : 
   11648       28343 : THREADED_TEST(CrossEval) {
   11649           6 :   v8::HandleScope scope(CcTest::isolate());
   11650          12 :   LocalContext other;
   11651          12 :   LocalContext current;
   11652             : 
   11653           6 :   Local<String> token = v8_str("<security token>");
   11654           6 :   other->SetSecurityToken(token);
   11655           6 :   current->SetSecurityToken(token);
   11656             : 
   11657             :   // Set up reference from current to other.
   11658          36 :   CHECK(current->Global()
   11659             :             ->Set(current.local(), v8_str("other"), other->Global())
   11660             :             .FromJust());
   11661             : 
   11662             :   // Check that new variables are introduced in other context.
   11663             :   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   11664           6 :   script->Run(current.local()).ToLocalChecked();
   11665             :   Local<Value> foo =
   11666          30 :       other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
   11667          12 :   CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
   11668          30 :   CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
   11669             : 
   11670             :   // Check that writing to non-existing properties introduces them in
   11671             :   // the other context.
   11672             :   script = v8_compile("other.eval('na = 1234')");
   11673           6 :   script->Run(current.local()).ToLocalChecked();
   11674          36 :   CHECK_EQ(1234, other->Global()
   11675             :                      ->Get(current.local(), v8_str("na"))
   11676             :                      .ToLocalChecked()
   11677             :                      ->Int32Value(other.local())
   11678             :                      .FromJust());
   11679          30 :   CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
   11680             : 
   11681             :   // Check that global variables in current context are not visible in other
   11682             :   // context.
   11683          12 :   v8::TryCatch try_catch(CcTest::isolate());
   11684             :   script = v8_compile("var bar = 42; other.eval('bar');");
   11685          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11686           6 :   CHECK(try_catch.HasCaught());
   11687           6 :   try_catch.Reset();
   11688             : 
   11689             :   // Check that local variables in current context are not visible in other
   11690             :   // context.
   11691             :   script = v8_compile(
   11692             :       "(function() { "
   11693             :       "  var baz = 87;"
   11694             :       "  return other.eval('baz');"
   11695             :       "})();");
   11696          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11697           6 :   CHECK(try_catch.HasCaught());
   11698           6 :   try_catch.Reset();
   11699             : 
   11700             :   // Check that global variables in the other environment are visible
   11701             :   // when evaluting code.
   11702          30 :   CHECK(other->Global()
   11703             :             ->Set(other.local(), v8_str("bis"), v8_num(1234))
   11704             :             .FromJust());
   11705             :   script = v8_compile("other.eval('bis')");
   11706          18 :   CHECK_EQ(1234, script->Run(current.local())
   11707             :                      .ToLocalChecked()
   11708             :                      ->Int32Value(current.local())
   11709             :                      .FromJust());
   11710           6 :   CHECK(!try_catch.HasCaught());
   11711             : 
   11712             :   // Check that the 'this' pointer points to the global object evaluating
   11713             :   // code.
   11714          36 :   CHECK(other->Global()
   11715             :             ->Set(current.local(), v8_str("t"), other->Global())
   11716             :             .FromJust());
   11717             :   script = v8_compile("other.eval('this == t')");
   11718           6 :   Local<Value> result = script->Run(current.local()).ToLocalChecked();
   11719           6 :   CHECK(result->IsTrue());
   11720           6 :   CHECK(!try_catch.HasCaught());
   11721             : 
   11722             :   // Check that variables introduced in with-statement are not visible in
   11723             :   // other context.
   11724             :   script = v8_compile("with({x:2}){other.eval('x')}");
   11725          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11726           6 :   CHECK(try_catch.HasCaught());
   11727           6 :   try_catch.Reset();
   11728             : 
   11729             :   // Check that you cannot use 'eval.call' with another object than the
   11730             :   // current global object.
   11731             :   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   11732          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11733          12 :   CHECK(try_catch.HasCaught());
   11734           6 : }
   11735             : 
   11736             : 
   11737             : // Test that calling eval in a context which has been detached from
   11738             : // its global proxy works.
   11739       28343 : THREADED_TEST(EvalInDetachedGlobal) {
   11740           6 :   v8::Isolate* isolate = CcTest::isolate();
   11741           6 :   v8::HandleScope scope(isolate);
   11742             : 
   11743           6 :   v8::Local<Context> context0 = Context::New(isolate);
   11744           6 :   v8::Local<Context> context1 = Context::New(isolate);
   11745           6 :   Local<String> token = v8_str("<security token>");
   11746           6 :   context0->SetSecurityToken(token);
   11747           6 :   context1->SetSecurityToken(token);
   11748             : 
   11749             :   // Set up function in context0 that uses eval from context0.
   11750           6 :   context0->Enter();
   11751             :   v8::Local<v8::Value> fun = CompileRun(
   11752             :       "var x = 42;"
   11753             :       "(function() {"
   11754             :       "  var e = eval;"
   11755             :       "  return function(s) { return e(s); }"
   11756           6 :       "})()");
   11757           6 :   context0->Exit();
   11758             : 
   11759             :   // Put the function into context1 and call it before and after
   11760             :   // detaching the global.  Before detaching, the call succeeds and
   11761             :   // after detaching undefined is returned.
   11762           6 :   context1->Enter();
   11763          24 :   CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
   11764             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   11765          12 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11766           6 :   context0->DetachGlobal();
   11767             :   x_value = CompileRun("fun('x')");
   11768           6 :   CHECK(x_value->IsUndefined());
   11769           6 :   context1->Exit();
   11770           6 : }
   11771             : 
   11772             : 
   11773       28343 : THREADED_TEST(CrossLazyLoad) {
   11774           6 :   v8::HandleScope scope(CcTest::isolate());
   11775          12 :   LocalContext other;
   11776          12 :   LocalContext current;
   11777             : 
   11778           6 :   Local<String> token = v8_str("<security token>");
   11779           6 :   other->SetSecurityToken(token);
   11780           6 :   current->SetSecurityToken(token);
   11781             : 
   11782             :   // Set up reference from current to other.
   11783          36 :   CHECK(current->Global()
   11784             :             ->Set(current.local(), v8_str("other"), other->Global())
   11785             :             .FromJust());
   11786             : 
   11787             :   // Trigger lazy loading in other context.
   11788             :   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11789           6 :   Local<Value> value = script->Run(current.local()).ToLocalChecked();
   11790          18 :   CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
   11791           6 : }
   11792             : 
   11793             : 
   11794         102 : static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11795          48 :   ApiTestFuzzer::Fuzz();
   11796          48 :   if (args.IsConstructCall()) {
   11797           6 :     if (args[0]->IsInt32()) {
   11798             :       args.GetReturnValue().Set(
   11799             :           v8_num(-args[0]
   11800           6 :                       ->Int32Value(args.GetIsolate()->GetCurrentContext())
   11801          18 :                       .FromJust()));
   11802          54 :       return;
   11803             :     }
   11804             :   }
   11805             : 
   11806             :   args.GetReturnValue().Set(args[0]);
   11807             : }
   11808             : 
   11809             : 
   11810             : // Test that a call handler can be set for objects which will allow
   11811             : // non-function objects created through the API to be called as
   11812             : // functions.
   11813       28343 : THREADED_TEST(CallAsFunction) {
   11814           6 :   LocalContext context;
   11815           6 :   v8::Isolate* isolate = context->GetIsolate();
   11816          12 :   v8::HandleScope scope(isolate);
   11817             : 
   11818             :   {
   11819           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11820           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11821           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   11822           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11823           6 :                                      .ToLocalChecked()
   11824           6 :                                      ->NewInstance(context.local())
   11825             :                                      .ToLocalChecked();
   11826          30 :     CHECK(context->Global()
   11827             :               ->Set(context.local(), v8_str("obj"), instance)
   11828             :               .FromJust());
   11829           6 :     v8::TryCatch try_catch(isolate);
   11830             :     Local<Value> value;
   11831           6 :     CHECK(!try_catch.HasCaught());
   11832             : 
   11833             :     value = CompileRun("obj(42)");
   11834           6 :     CHECK(!try_catch.HasCaught());
   11835          12 :     CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11836             : 
   11837             :     value = CompileRun("(function(o){return o(49)})(obj)");
   11838           6 :     CHECK(!try_catch.HasCaught());
   11839          12 :     CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
   11840             : 
   11841             :     // test special case of call as function
   11842             :     value = CompileRun("[obj]['0'](45)");
   11843           6 :     CHECK(!try_catch.HasCaught());
   11844          12 :     CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
   11845             : 
   11846             :     value = CompileRun(
   11847             :         "obj.call = Function.prototype.call;"
   11848             :         "obj.call(null, 87)");
   11849           6 :     CHECK(!try_catch.HasCaught());
   11850          12 :     CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
   11851             : 
   11852             :     // Regression tests for bug #1116356: Calling call through call/apply
   11853             :     // must work for non-function receivers.
   11854             :     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11855             :     value = CompileRun(apply_99);
   11856           6 :     CHECK(!try_catch.HasCaught());
   11857          12 :     CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
   11858             : 
   11859             :     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11860             :     value = CompileRun(call_17);
   11861           6 :     CHECK(!try_catch.HasCaught());
   11862          12 :     CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
   11863             : 
   11864             :     // Check that the call-as-function handler can be called through new.
   11865             :     value = CompileRun("new obj(43)");
   11866           6 :     CHECK(!try_catch.HasCaught());
   11867          12 :     CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
   11868             : 
   11869             :     // Check that the call-as-function handler can be called through
   11870             :     // the API.
   11871           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11872          12 :     value = instance->CallAsFunction(context.local(), instance, 1, args)
   11873           6 :                 .ToLocalChecked();
   11874           6 :     CHECK(!try_catch.HasCaught());
   11875          12 :     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11876             :   }
   11877             : 
   11878             :   {
   11879           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11880           6 :     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11881             :     USE(instance_template);
   11882           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11883           6 :                                      .ToLocalChecked()
   11884           6 :                                      ->NewInstance(context.local())
   11885             :                                      .ToLocalChecked();
   11886          30 :     CHECK(context->Global()
   11887             :               ->Set(context.local(), v8_str("obj2"), instance)
   11888             :               .FromJust());
   11889           6 :     v8::TryCatch try_catch(isolate);
   11890             :     Local<Value> value;
   11891           6 :     CHECK(!try_catch.HasCaught());
   11892             : 
   11893             :     // Call an object without call-as-function handler through the JS
   11894             :     value = CompileRun("obj2(28)");
   11895           6 :     CHECK(value.IsEmpty());
   11896           6 :     CHECK(try_catch.HasCaught());
   11897          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11898             :     // TODO(verwaest): Better message
   11899           6 :     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
   11900           6 :     try_catch.Reset();
   11901             : 
   11902             :     // Call an object without call-as-function handler through the API
   11903           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11904          12 :     CHECK(
   11905             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11906           6 :     CHECK(try_catch.HasCaught());
   11907          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11908           6 :     CHECK_EQ(0,
   11909             :              strcmp("TypeError: object is not a function", *exception_value2));
   11910          12 :     try_catch.Reset();
   11911             :   }
   11912             : 
   11913             :   {
   11914           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11915           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11916           6 :     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11917           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11918           6 :                                      .ToLocalChecked()
   11919           6 :                                      ->NewInstance(context.local())
   11920             :                                      .ToLocalChecked();
   11921          30 :     CHECK(context->Global()
   11922             :               ->Set(context.local(), v8_str("obj3"), instance)
   11923             :               .FromJust());
   11924           6 :     v8::TryCatch try_catch(isolate);
   11925             :     Local<Value> value;
   11926           6 :     CHECK(!try_catch.HasCaught());
   11927             : 
   11928             :     // Catch the exception which is thrown by call-as-function handler
   11929             :     value = CompileRun("obj3(22)");
   11930           6 :     CHECK(try_catch.HasCaught());
   11931          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11932           6 :     CHECK_EQ(0, strcmp("22", *exception_value1));
   11933           6 :     try_catch.Reset();
   11934             : 
   11935           6 :     v8::Local<Value> args[] = {v8_num(23)};
   11936          12 :     CHECK(
   11937             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11938           6 :     CHECK(try_catch.HasCaught());
   11939          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11940           6 :     CHECK_EQ(0, strcmp("23", *exception_value2));
   11941          12 :     try_catch.Reset();
   11942             :   }
   11943             : 
   11944             :   {
   11945           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11946           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11947           6 :     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11948           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11949           6 :                                      .ToLocalChecked()
   11950           6 :                                      ->NewInstance(context.local())
   11951             :                                      .ToLocalChecked();
   11952             : 
   11953             :     Local<v8::Value> a1 =
   11954             :         instance
   11955             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11956          12 :                              nullptr)
   11957           6 :             .ToLocalChecked();
   11958           6 :     CHECK(a1->StrictEquals(instance));
   11959             :     Local<v8::Value> a2 =
   11960          12 :         instance->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11961           6 :             .ToLocalChecked();
   11962           6 :     CHECK(a2->StrictEquals(instance));
   11963             :     Local<v8::Value> a3 =
   11964           6 :         instance->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11965           6 :             .ToLocalChecked();
   11966           6 :     CHECK(a3->StrictEquals(instance));
   11967             :     Local<v8::Value> a4 =
   11968          18 :         instance->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11969           6 :             .ToLocalChecked();
   11970           6 :     CHECK(a4->StrictEquals(instance));
   11971             :     Local<v8::Value> a5 =
   11972          12 :         instance->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11973           6 :             .ToLocalChecked();
   11974           6 :     CHECK(a5->StrictEquals(instance));
   11975             :   }
   11976             : 
   11977             :   {
   11978             :     CompileRun(
   11979             :         "function ReturnThisSloppy() {"
   11980             :         "  return this;"
   11981             :         "}"
   11982             :         "function ReturnThisStrict() {"
   11983             :         "  'use strict';"
   11984             :         "  return this;"
   11985             :         "}");
   11986             :     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   11987             :         context->Global()
   11988          24 :             ->Get(context.local(), v8_str("ReturnThisSloppy"))
   11989           6 :             .ToLocalChecked());
   11990             :     Local<Function> ReturnThisStrict = Local<Function>::Cast(
   11991             :         context->Global()
   11992          24 :             ->Get(context.local(), v8_str("ReturnThisStrict"))
   11993           6 :             .ToLocalChecked());
   11994             : 
   11995             :     Local<v8::Value> a1 =
   11996             :         ReturnThisSloppy
   11997             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11998          12 :                              nullptr)
   11999           6 :             .ToLocalChecked();
   12000          12 :     CHECK(a1->StrictEquals(context->Global()));
   12001             :     Local<v8::Value> a2 =
   12002             :         ReturnThisSloppy
   12003          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   12004           6 :             .ToLocalChecked();
   12005          12 :     CHECK(a2->StrictEquals(context->Global()));
   12006             :     Local<v8::Value> a3 =
   12007             :         ReturnThisSloppy
   12008           6 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   12009           6 :             .ToLocalChecked();
   12010           6 :     CHECK(a3->IsNumberObject());
   12011           6 :     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   12012             :     Local<v8::Value> a4 =
   12013             :         ReturnThisSloppy
   12014          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   12015           6 :             .ToLocalChecked();
   12016           6 :     CHECK(a4->IsStringObject());
   12017          18 :     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   12018             :     Local<v8::Value> a5 =
   12019             :         ReturnThisSloppy
   12020          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   12021           6 :             .ToLocalChecked();
   12022           6 :     CHECK(a5->IsBooleanObject());
   12023           6 :     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   12024             : 
   12025             :     Local<v8::Value> a6 =
   12026             :         ReturnThisStrict
   12027             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   12028          12 :                              nullptr)
   12029           6 :             .ToLocalChecked();
   12030           6 :     CHECK(a6->IsUndefined());
   12031             :     Local<v8::Value> a7 =
   12032             :         ReturnThisStrict
   12033          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   12034           6 :             .ToLocalChecked();
   12035           6 :     CHECK(a7->IsNull());
   12036             :     Local<v8::Value> a8 =
   12037             :         ReturnThisStrict
   12038           6 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   12039           6 :             .ToLocalChecked();
   12040           6 :     CHECK(a8->StrictEquals(v8_num(42)));
   12041             :     Local<v8::Value> a9 =
   12042             :         ReturnThisStrict
   12043          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   12044           6 :             .ToLocalChecked();
   12045          12 :     CHECK(a9->StrictEquals(v8_str("hello")));
   12046             :     Local<v8::Value> a10 =
   12047             :         ReturnThisStrict
   12048          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   12049           6 :             .ToLocalChecked();
   12050           6 :     CHECK(a10->StrictEquals(v8::True(isolate)));
   12051           6 :   }
   12052           6 : }
   12053             : 
   12054             : 
   12055             : // Check whether a non-function object is callable.
   12056       28343 : THREADED_TEST(CallableObject) {
   12057           6 :   LocalContext context;
   12058           6 :   v8::Isolate* isolate = context->GetIsolate();
   12059          12 :   v8::HandleScope scope(isolate);
   12060             : 
   12061             :   {
   12062           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   12063           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   12064             :     Local<Object> instance =
   12065           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   12066           6 :     v8::TryCatch try_catch(isolate);
   12067             : 
   12068           6 :     CHECK(instance->IsCallable());
   12069           6 :     CHECK(!try_catch.HasCaught());
   12070             :   }
   12071             : 
   12072             :   {
   12073           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   12074             :     Local<Object> instance =
   12075          12 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   12076           6 :     v8::TryCatch try_catch(isolate);
   12077             : 
   12078           6 :     CHECK(!instance->IsCallable());
   12079           6 :     CHECK(!try_catch.HasCaught());
   12080             :   }
   12081             : 
   12082             :   {
   12083             :     Local<FunctionTemplate> function_template =
   12084           6 :         FunctionTemplate::New(isolate, call_as_function);
   12085             :     Local<Function> function =
   12086          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   12087             :     Local<Object> instance = function;
   12088           6 :     v8::TryCatch try_catch(isolate);
   12089             : 
   12090           6 :     CHECK(instance->IsCallable());
   12091           6 :     CHECK(!try_catch.HasCaught());
   12092             :   }
   12093             : 
   12094             :   {
   12095           6 :     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   12096             :     Local<Function> function =
   12097          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   12098             :     Local<Object> instance = function;
   12099           6 :     v8::TryCatch try_catch(isolate);
   12100             : 
   12101           6 :     CHECK(instance->IsCallable());
   12102           6 :     CHECK(!try_catch.HasCaught());
   12103           6 :   }
   12104           6 : }
   12105             : 
   12106             : 
   12107       28343 : THREADED_TEST(Regress567998) {
   12108           6 :   LocalContext env;
   12109          12 :   v8::HandleScope scope(env->GetIsolate());
   12110             : 
   12111             :   Local<v8::FunctionTemplate> desc =
   12112           6 :       v8::FunctionTemplate::New(env->GetIsolate());
   12113          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   12114          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
   12115             : 
   12116           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   12117           6 :                               .ToLocalChecked()
   12118           6 :                               ->NewInstance(env.local())
   12119             :                               .ToLocalChecked();
   12120          30 :   CHECK(
   12121             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   12122             : 
   12123           6 :   ExpectString("undetectable.toString()", "[object Object]");
   12124           6 :   ExpectString("typeof undetectable", "undefined");
   12125           6 :   ExpectString("typeof(undetectable)", "undefined");
   12126           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
   12127           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
   12128           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   12129           6 :   ExpectBoolean("!undetectable", true);
   12130             : 
   12131           6 :   ExpectObject("true&&undetectable", obj);
   12132           6 :   ExpectBoolean("false&&undetectable", false);
   12133           6 :   ExpectBoolean("true||undetectable", true);
   12134           6 :   ExpectObject("false||undetectable", obj);
   12135             : 
   12136           6 :   ExpectObject("undetectable&&true", obj);
   12137           6 :   ExpectObject("undetectable&&false", obj);
   12138           6 :   ExpectBoolean("undetectable||true", true);
   12139           6 :   ExpectBoolean("undetectable||false", false);
   12140             : 
   12141           6 :   ExpectBoolean("undetectable==null", true);
   12142           6 :   ExpectBoolean("null==undetectable", true);
   12143           6 :   ExpectBoolean("undetectable==undefined", true);
   12144           6 :   ExpectBoolean("undefined==undetectable", true);
   12145           6 :   ExpectBoolean("undetectable==undetectable", true);
   12146             : 
   12147           6 :   ExpectBoolean("undetectable===null", false);
   12148           6 :   ExpectBoolean("null===undetectable", false);
   12149           6 :   ExpectBoolean("undetectable===undefined", false);
   12150           6 :   ExpectBoolean("undefined===undetectable", false);
   12151          12 :   ExpectBoolean("undetectable===undetectable", true);
   12152           6 : }
   12153             : 
   12154             : 
   12155        1206 : static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   12156        1206 :   v8::HandleScope scope(isolate);
   12157        1206 :   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   12158      600000 :   for (int i = 0; i < iterations; i++) {
   12159      600000 :     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   12160             :   }
   12161        1200 :   return Recurse(isolate, depth - 1, iterations);
   12162             : }
   12163             : 
   12164             : 
   12165       28343 : THREADED_TEST(HandleIteration) {
   12166             :   static const int kIterations = 500;
   12167             :   static const int kNesting = 200;
   12168           6 :   LocalContext context;
   12169           6 :   v8::Isolate* isolate = context->GetIsolate();
   12170          12 :   v8::HandleScope scope0(isolate);
   12171           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12172             :   {
   12173           6 :     v8::HandleScope scope1(isolate);
   12174           6 :     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12175        3006 :     for (int i = 0; i < kIterations; i++) {
   12176        3000 :       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12177        3000 :       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   12178             :     }
   12179             : 
   12180           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12181             :     {
   12182           6 :       v8::HandleScope scope2(CcTest::isolate());
   12183        3006 :       for (int j = 0; j < kIterations; j++) {
   12184        3000 :         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12185        3000 :         CHECK_EQ(j + 1 + kIterations,
   12186             :                  v8::HandleScope::NumberOfHandles(isolate));
   12187           6 :       }
   12188             :     }
   12189           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12190             :   }
   12191           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12192          12 :   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   12193           6 : }
   12194             : 
   12195             : 
   12196        4994 : static void InterceptorCallICFastApi(
   12197             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12198        4994 :   ApiTestFuzzer::Fuzz();
   12199        4994 :   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   12200             :   int* call_count =
   12201        4994 :       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   12202        4994 :   ++(*call_count);
   12203        4994 :   if ((*call_count) % 20 == 0) {
   12204         231 :     CcTest::CollectAllGarbage();
   12205             :   }
   12206        4994 : }
   12207             : 
   12208        2200 : static void FastApiCallback_TrivialSignature(
   12209        8800 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12210        2200 :   ApiTestFuzzer::Fuzz();
   12211        2200 :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   12212        2200 :   v8::Isolate* isolate = CcTest::isolate();
   12213        2200 :   CHECK_EQ(isolate, args.GetIsolate());
   12214        6600 :   CHECK(args.This()
   12215             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12216             :             .FromJust());
   12217        8800 :   CHECK(args.Data()
   12218             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12219             :             .FromJust());
   12220             :   args.GetReturnValue().Set(
   12221        8800 :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12222        2200 : }
   12223             : 
   12224        6127 : static void FastApiCallback_SimpleSignature(
   12225       30635 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12226        6127 :   ApiTestFuzzer::Fuzz();
   12227        6127 :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   12228        6127 :   v8::Isolate* isolate = CcTest::isolate();
   12229        6127 :   CHECK_EQ(isolate, args.GetIsolate());
   12230       24508 :   CHECK(args.This()
   12231             :             ->GetPrototype()
   12232             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12233             :             .FromJust());
   12234       24508 :   CHECK(args.Data()
   12235             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12236             :             .FromJust());
   12237             :   // Note, we're using HasRealNamedProperty instead of Has to avoid
   12238             :   // invoking the interceptor again.
   12239       24508 :   CHECK(args.Holder()
   12240             :             ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
   12241             :             .FromJust());
   12242             :   args.GetReturnValue().Set(
   12243       24508 :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12244        6127 : }
   12245             : 
   12246             : 
   12247             : // Helper to maximize the odds of object moving.
   12248         291 : static void GenerateSomeGarbage() {
   12249             :   CompileRun(
   12250             :       "var garbage;"
   12251             :       "for (var i = 0; i < 1000; i++) {"
   12252             :       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   12253             :       "}"
   12254             :       "garbage = undefined;");
   12255         291 : }
   12256             : 
   12257             : 
   12258         180 : void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12259             :   static int count = 0;
   12260         180 :   if (count++ % 3 == 0) {
   12261          60 :     CcTest::CollectAllGarbage();
   12262             :     // This should move the stub
   12263          60 :     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   12264             :   }
   12265         180 : }
   12266             : 
   12267             : 
   12268       28343 : THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   12269           6 :   LocalContext context;
   12270           6 :   v8::Isolate* isolate = context->GetIsolate();
   12271          12 :   v8::HandleScope scope(isolate);
   12272             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12273           6 :       v8::ObjectTemplate::New(isolate);
   12274             :   nativeobject_templ->Set(isolate, "callback",
   12275             :                           v8::FunctionTemplate::New(isolate,
   12276          12 :                                                     DirectApiCallback));
   12277             :   v8::Local<v8::Object> nativeobject_obj =
   12278           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12279          30 :   CHECK(context->Global()
   12280             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12281             :             .FromJust());
   12282             :   // call the api function multiple times to ensure direct call stub creation.
   12283             :   CompileRun(
   12284             :         "function f() {"
   12285             :         "  for (var i = 1; i <= 30; i++) {"
   12286             :         "    nativeobject.callback();"
   12287             :         "  }"
   12288             :         "}"
   12289           6 :         "f();");
   12290           6 : }
   12291             : 
   12292             : 
   12293          30 : void ThrowingDirectApiCallback(
   12294          30 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12295          60 :   args.GetIsolate()->ThrowException(v8_str("g"));
   12296          30 : }
   12297             : 
   12298             : 
   12299       28343 : THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   12300           6 :   LocalContext context;
   12301           6 :   v8::Isolate* isolate = context->GetIsolate();
   12302          12 :   v8::HandleScope scope(isolate);
   12303             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12304           6 :       v8::ObjectTemplate::New(isolate);
   12305             :   nativeobject_templ->Set(isolate, "callback",
   12306             :                           v8::FunctionTemplate::New(isolate,
   12307          12 :                                                     ThrowingDirectApiCallback));
   12308             :   v8::Local<v8::Object> nativeobject_obj =
   12309           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12310          30 :   CHECK(context->Global()
   12311             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12312             :             .FromJust());
   12313             :   // call the api function multiple times to ensure direct call stub creation.
   12314             :   v8::Local<Value> result = CompileRun(
   12315             :       "var result = '';"
   12316             :       "function f() {"
   12317             :       "  for (var i = 1; i <= 5; i++) {"
   12318             :       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   12319             :       "  }"
   12320             :       "}"
   12321           6 :       "f(); result;");
   12322          24 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12323           6 : }
   12324             : 
   12325             : 
   12326             : static int p_getter_count_3;
   12327             : 
   12328             : 
   12329         341 : static Local<Value> DoDirectGetter() {
   12330         341 :   if (++p_getter_count_3 % 3 == 0) {
   12331         110 :     CcTest::CollectAllGarbage();
   12332         110 :     GenerateSomeGarbage();
   12333             :   }
   12334         341 :   return v8_str("Direct Getter Result");
   12335             : }
   12336             : 
   12337             : 
   12338         341 : static void DirectGetterCallback(
   12339             :     Local<String> name,
   12340             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12341         341 :   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   12342         341 :   info.GetReturnValue().Set(DoDirectGetter());
   12343         341 : }
   12344             : 
   12345             : 
   12346             : template<typename Accessor>
   12347          11 : static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   12348          11 :   LocalContext context;
   12349          11 :   v8::Isolate* isolate = context->GetIsolate();
   12350          22 :   v8::HandleScope scope(isolate);
   12351          11 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12352          11 :   obj->SetAccessor(v8_str("p1"), accessor);
   12353          66 :   CHECK(context->Global()
   12354             :             ->Set(context.local(), v8_str("o1"),
   12355             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12356             :             .FromJust());
   12357          11 :   p_getter_count_3 = 0;
   12358             :   v8::Local<v8::Value> result = CompileRun(
   12359             :       "function f() {"
   12360             :       "  for (var i = 0; i < 30; i++) o1.p1;"
   12361             :       "  return o1.p1"
   12362             :       "}"
   12363          11 :       "f();");
   12364          33 :   CHECK(v8_str("Direct Getter Result")
   12365             :             ->Equals(context.local(), result)
   12366             :             .FromJust());
   12367          22 :   CHECK_EQ(31, p_getter_count_3);
   12368          11 : }
   12369             : 
   12370             : 
   12371       56690 : THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12372          11 :   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12373          11 : }
   12374             : 
   12375             : 
   12376          30 : void ThrowingDirectGetterCallback(
   12377             :     Local<String> name,
   12378             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   12379          60 :   info.GetIsolate()->ThrowException(v8_str("g"));
   12380          30 : }
   12381             : 
   12382             : 
   12383       28343 : THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12384           6 :   LocalContext context;
   12385           6 :   v8::Isolate* isolate = context->GetIsolate();
   12386          12 :   v8::HandleScope scope(isolate);
   12387           6 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12388           6 :   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12389          36 :   CHECK(context->Global()
   12390             :             ->Set(context.local(), v8_str("o1"),
   12391             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12392             :             .FromJust());
   12393             :   v8::Local<Value> result = CompileRun(
   12394             :       "var result = '';"
   12395             :       "for (var i = 0; i < 5; i++) {"
   12396             :       "    try { o1.p1; } catch (e) { result += e; }"
   12397             :       "}"
   12398           6 :       "result;");
   12399          24 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12400           6 : }
   12401             : 
   12402             : 
   12403       56690 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12404          11 :   int interceptor_call_count = 0;
   12405          11 :   v8::Isolate* isolate = CcTest::isolate();
   12406          11 :   v8::HandleScope scope(isolate);
   12407             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12408          11 :       v8::FunctionTemplate::New(isolate);
   12409             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12410             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12411          22 :       v8::Local<v8::Signature>());
   12412          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12413          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12414          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12415             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12416             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12417          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12418          22 :   LocalContext context;
   12419             :   v8::Local<v8::Function> fun =
   12420          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12421          11 :   GenerateSomeGarbage();
   12422          66 :   CHECK(context->Global()
   12423             :             ->Set(context.local(), v8_str("o"),
   12424             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12425             :             .FromJust());
   12426             :   CompileRun(
   12427             :       "var result = 0;"
   12428             :       "for (var i = 0; i < 100; i++) {"
   12429             :       "  result = o.method(41);"
   12430             :       "}");
   12431          66 :   CHECK_EQ(42, context->Global()
   12432             :                    ->Get(context.local(), v8_str("result"))
   12433             :                    .ToLocalChecked()
   12434             :                    ->Int32Value(context.local())
   12435             :                    .FromJust());
   12436          22 :   CHECK_EQ(100, interceptor_call_count);
   12437          11 : }
   12438             : 
   12439             : 
   12440       56690 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
   12441          11 :   int interceptor_call_count = 0;
   12442          11 :   v8::Isolate* isolate = CcTest::isolate();
   12443          11 :   v8::HandleScope scope(isolate);
   12444             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12445          11 :       v8::FunctionTemplate::New(isolate);
   12446             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12447             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12448          22 :       v8::Signature::New(isolate, fun_templ));
   12449          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12450          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12451          11 :   fun_templ->SetHiddenPrototype(true);
   12452          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12453             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12454             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12455          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12456          22 :   LocalContext context;
   12457             :   v8::Local<v8::Function> fun =
   12458          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12459          11 :   GenerateSomeGarbage();
   12460          66 :   CHECK(context->Global()
   12461             :             ->Set(context.local(), v8_str("o"),
   12462             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12463             :             .FromJust());
   12464             :   CompileRun(
   12465             :       "o.foo = 17;"
   12466             :       "var receiver = {};"
   12467             :       "receiver.__proto__ = o;"
   12468             :       "var result = 0;"
   12469             :       "for (var i = 0; i < 100; i++) {"
   12470             :       "  result = receiver.method(41);"
   12471             :       "}");
   12472          66 :   CHECK_EQ(42, context->Global()
   12473             :                    ->Get(context.local(), v8_str("result"))
   12474             :                    .ToLocalChecked()
   12475             :                    ->Int32Value(context.local())
   12476             :                    .FromJust());
   12477          22 :   CHECK_EQ(100, interceptor_call_count);
   12478          11 : }
   12479             : 
   12480             : 
   12481       56690 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
   12482          11 :   int interceptor_call_count = 0;
   12483          11 :   v8::Isolate* isolate = CcTest::isolate();
   12484          11 :   v8::HandleScope scope(isolate);
   12485             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12486          11 :       v8::FunctionTemplate::New(isolate);
   12487             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12488             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12489          22 :       v8::Signature::New(isolate, fun_templ));
   12490          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12491          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12492          11 :   fun_templ->SetHiddenPrototype(true);
   12493          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12494             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12495             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12496          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12497          22 :   LocalContext context;
   12498             :   v8::Local<v8::Function> fun =
   12499          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12500          11 :   GenerateSomeGarbage();
   12501          66 :   CHECK(context->Global()
   12502             :             ->Set(context.local(), v8_str("o"),
   12503             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12504             :             .FromJust());
   12505             :   CompileRun(
   12506             :       "o.foo = 17;"
   12507             :       "var receiver = {};"
   12508             :       "receiver.__proto__ = o;"
   12509             :       "var result = 0;"
   12510             :       "var saved_result = 0;"
   12511             :       "for (var i = 0; i < 100; i++) {"
   12512             :       "  result = receiver.method(41);"
   12513             :       "  if (i == 50) {"
   12514             :       "    saved_result = result;"
   12515             :       "    receiver = {method: function(x) { return x - 1 }};"
   12516             :       "  }"
   12517             :       "}");
   12518          66 :   CHECK_EQ(40, context->Global()
   12519             :                    ->Get(context.local(), v8_str("result"))
   12520             :                    .ToLocalChecked()
   12521             :                    ->Int32Value(context.local())
   12522             :                    .FromJust());
   12523          66 :   CHECK_EQ(42, context->Global()
   12524             :                    ->Get(context.local(), v8_str("saved_result"))
   12525             :                    .ToLocalChecked()
   12526             :                    ->Int32Value(context.local())
   12527             :                    .FromJust());
   12528          22 :   CHECK_GE(interceptor_call_count, 50);
   12529          11 : }
   12530             : 
   12531             : 
   12532       56690 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
   12533          11 :   int interceptor_call_count = 0;
   12534          11 :   v8::Isolate* isolate = CcTest::isolate();
   12535          11 :   v8::HandleScope scope(isolate);
   12536             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12537          11 :       v8::FunctionTemplate::New(isolate);
   12538             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12539             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12540          22 :       v8::Signature::New(isolate, fun_templ));
   12541          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12542          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12543          11 :   fun_templ->SetHiddenPrototype(true);
   12544          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12545             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12546             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12547          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12548          22 :   LocalContext context;
   12549             :   v8::Local<v8::Function> fun =
   12550          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12551          11 :   GenerateSomeGarbage();
   12552          66 :   CHECK(context->Global()
   12553             :             ->Set(context.local(), v8_str("o"),
   12554             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12555             :             .FromJust());
   12556             :   CompileRun(
   12557             :       "o.foo = 17;"
   12558             :       "var receiver = {};"
   12559             :       "receiver.__proto__ = o;"
   12560             :       "var result = 0;"
   12561             :       "var saved_result = 0;"
   12562             :       "for (var i = 0; i < 100; i++) {"
   12563             :       "  result = receiver.method(41);"
   12564             :       "  if (i == 50) {"
   12565             :       "    saved_result = result;"
   12566             :       "    o.method = function(x) { return x - 1 };"
   12567             :       "  }"
   12568             :       "}");
   12569          66 :   CHECK_EQ(40, context->Global()
   12570             :                    ->Get(context.local(), v8_str("result"))
   12571             :                    .ToLocalChecked()
   12572             :                    ->Int32Value(context.local())
   12573             :                    .FromJust());
   12574          66 :   CHECK_EQ(42, context->Global()
   12575             :                    ->Get(context.local(), v8_str("saved_result"))
   12576             :                    .ToLocalChecked()
   12577             :                    ->Int32Value(context.local())
   12578             :                    .FromJust());
   12579          22 :   CHECK_GE(interceptor_call_count, 50);
   12580          11 : }
   12581             : 
   12582             : 
   12583       56690 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
   12584          11 :   int interceptor_call_count = 0;
   12585          11 :   v8::Isolate* isolate = CcTest::isolate();
   12586          11 :   v8::HandleScope scope(isolate);
   12587             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12588          11 :       v8::FunctionTemplate::New(isolate);
   12589             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12590             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12591          22 :       v8::Signature::New(isolate, fun_templ));
   12592          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12593          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12594          11 :   fun_templ->SetHiddenPrototype(true);
   12595          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12596             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12597             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12598          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12599          22 :   LocalContext context;
   12600             :   v8::Local<v8::Function> fun =
   12601          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12602          11 :   GenerateSomeGarbage();
   12603          66 :   CHECK(context->Global()
   12604             :             ->Set(context.local(), v8_str("o"),
   12605             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12606             :             .FromJust());
   12607          22 :   v8::TryCatch try_catch(isolate);
   12608             :   CompileRun(
   12609             :       "o.foo = 17;"
   12610             :       "var receiver = {};"
   12611             :       "receiver.__proto__ = o;"
   12612             :       "var result = 0;"
   12613             :       "var saved_result = 0;"
   12614             :       "for (var i = 0; i < 100; i++) {"
   12615             :       "  result = receiver.method(41);"
   12616             :       "  if (i == 50) {"
   12617             :       "    saved_result = result;"
   12618             :       "    receiver = 333;"
   12619             :       "  }"
   12620             :       "}");
   12621          11 :   CHECK(try_catch.HasCaught());
   12622             :   // TODO(verwaest): Adjust message.
   12623          55 :   CHECK(
   12624             :       v8_str("TypeError: receiver.method is not a function")
   12625             :           ->Equals(
   12626             :               context.local(),
   12627             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12628             :           .FromJust());
   12629          66 :   CHECK_EQ(42, context->Global()
   12630             :                    ->Get(context.local(), v8_str("saved_result"))
   12631             :                    .ToLocalChecked()
   12632             :                    ->Int32Value(context.local())
   12633             :                    .FromJust());
   12634          22 :   CHECK_GE(interceptor_call_count, 50);
   12635          11 : }
   12636             : 
   12637             : 
   12638       56690 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
   12639          11 :   int interceptor_call_count = 0;
   12640          11 :   v8::Isolate* isolate = CcTest::isolate();
   12641          11 :   v8::HandleScope scope(isolate);
   12642             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12643          11 :       v8::FunctionTemplate::New(isolate);
   12644             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12645             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12646          22 :       v8::Signature::New(isolate, fun_templ));
   12647          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12648          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12649          11 :   fun_templ->SetHiddenPrototype(true);
   12650          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12651             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12652             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12653          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12654          22 :   LocalContext context;
   12655             :   v8::Local<v8::Function> fun =
   12656          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12657          11 :   GenerateSomeGarbage();
   12658          66 :   CHECK(context->Global()
   12659             :             ->Set(context.local(), v8_str("o"),
   12660             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12661             :             .FromJust());
   12662          22 :   v8::TryCatch try_catch(isolate);
   12663             :   CompileRun(
   12664             :       "o.foo = 17;"
   12665             :       "var receiver = {};"
   12666             :       "receiver.__proto__ = o;"
   12667             :       "var result = 0;"
   12668             :       "var saved_result = 0;"
   12669             :       "for (var i = 0; i < 100; i++) {"
   12670             :       "  result = receiver.method(41);"
   12671             :       "  if (i == 50) {"
   12672             :       "    saved_result = result;"
   12673             :       "    receiver = {method: receiver.method};"
   12674             :       "  }"
   12675             :       "}");
   12676          11 :   CHECK(try_catch.HasCaught());
   12677          55 :   CHECK(
   12678             :       v8_str("TypeError: Illegal invocation")
   12679             :           ->Equals(
   12680             :               context.local(),
   12681             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12682             :           .FromJust());
   12683          66 :   CHECK_EQ(42, context->Global()
   12684             :                    ->Get(context.local(), v8_str("saved_result"))
   12685             :                    .ToLocalChecked()
   12686             :                    ->Int32Value(context.local())
   12687             :                    .FromJust());
   12688          22 :   CHECK_GE(interceptor_call_count, 50);
   12689          11 : }
   12690             : 
   12691             : 
   12692       56690 : THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12693          11 :   v8::Isolate* isolate = CcTest::isolate();
   12694          11 :   v8::HandleScope scope(isolate);
   12695             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12696          11 :       v8::FunctionTemplate::New(isolate);
   12697             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12698             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12699          22 :       v8::Local<v8::Signature>());
   12700          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12701          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12702          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12703             :   USE(templ);
   12704          22 :   LocalContext context;
   12705             :   v8::Local<v8::Function> fun =
   12706          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12707          11 :   GenerateSomeGarbage();
   12708          66 :   CHECK(context->Global()
   12709             :             ->Set(context.local(), v8_str("o"),
   12710             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12711             :             .FromJust());
   12712             :   CompileRun(
   12713             :       "var result = 0;"
   12714             :       "for (var i = 0; i < 100; i++) {"
   12715             :       "  result = o.method(41);"
   12716             :       "}");
   12717             : 
   12718          66 :   CHECK_EQ(42, context->Global()
   12719             :                    ->Get(context.local(), v8_str("result"))
   12720             :                    .ToLocalChecked()
   12721             :                    ->Int32Value(context.local())
   12722          11 :                    .FromJust());
   12723          11 : }
   12724             : 
   12725             : 
   12726       56690 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
   12727          11 :   v8::Isolate* isolate = CcTest::isolate();
   12728          11 :   v8::HandleScope scope(isolate);
   12729             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12730          11 :       v8::FunctionTemplate::New(isolate);
   12731             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12732             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12733          22 :       v8::Signature::New(isolate, fun_templ));
   12734          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12735          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12736          11 :   fun_templ->SetHiddenPrototype(true);
   12737          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12738          11 :   CHECK(!templ.IsEmpty());
   12739          22 :   LocalContext context;
   12740             :   v8::Local<v8::Function> fun =
   12741          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12742          11 :   GenerateSomeGarbage();
   12743          66 :   CHECK(context->Global()
   12744             :             ->Set(context.local(), v8_str("o"),
   12745             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12746             :             .FromJust());
   12747             :   CompileRun(
   12748             :       "o.foo = 17;"
   12749             :       "var receiver = {};"
   12750             :       "receiver.__proto__ = o;"
   12751             :       "var result = 0;"
   12752             :       "for (var i = 0; i < 100; i++) {"
   12753             :       "  result = receiver.method(41);"
   12754             :       "}");
   12755             : 
   12756          66 :   CHECK_EQ(42, context->Global()
   12757             :                    ->Get(context.local(), v8_str("result"))
   12758             :                    .ToLocalChecked()
   12759             :                    ->Int32Value(context.local())
   12760          11 :                    .FromJust());
   12761          11 : }
   12762             : 
   12763             : 
   12764       56690 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
   12765          11 :   v8::Isolate* isolate = CcTest::isolate();
   12766          11 :   v8::HandleScope scope(isolate);
   12767             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12768          11 :       v8::FunctionTemplate::New(isolate);
   12769             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12770             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12771          22 :       v8::Signature::New(isolate, fun_templ));
   12772          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12773          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12774          11 :   fun_templ->SetHiddenPrototype(true);
   12775          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12776          11 :   CHECK(!templ.IsEmpty());
   12777          22 :   LocalContext context;
   12778             :   v8::Local<v8::Function> fun =
   12779          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12780          11 :   GenerateSomeGarbage();
   12781          66 :   CHECK(context->Global()
   12782             :             ->Set(context.local(), v8_str("o"),
   12783             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12784             :             .FromJust());
   12785             :   CompileRun(
   12786             :       "o.foo = 17;"
   12787             :       "var receiver = {};"
   12788             :       "receiver.__proto__ = o;"
   12789             :       "var result = 0;"
   12790             :       "var saved_result = 0;"
   12791             :       "for (var i = 0; i < 100; i++) {"
   12792             :       "  result = receiver.method(41);"
   12793             :       "  if (i == 50) {"
   12794             :       "    saved_result = result;"
   12795             :       "    receiver = {method: function(x) { return x - 1 }};"
   12796             :       "  }"
   12797             :       "}");
   12798          66 :   CHECK_EQ(40, context->Global()
   12799             :                    ->Get(context.local(), v8_str("result"))
   12800             :                    .ToLocalChecked()
   12801             :                    ->Int32Value(context.local())
   12802             :                    .FromJust());
   12803          66 :   CHECK_EQ(42, context->Global()
   12804             :                    ->Get(context.local(), v8_str("saved_result"))
   12805             :                    .ToLocalChecked()
   12806             :                    ->Int32Value(context.local())
   12807          11 :                    .FromJust());
   12808          11 : }
   12809             : 
   12810             : 
   12811       56690 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
   12812          11 :   v8::Isolate* isolate = CcTest::isolate();
   12813          11 :   v8::HandleScope scope(isolate);
   12814             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12815          11 :       v8::FunctionTemplate::New(isolate);
   12816             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12817             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12818          22 :       v8::Signature::New(isolate, fun_templ));
   12819          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12820          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12821          11 :   fun_templ->SetHiddenPrototype(true);
   12822          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12823          11 :   CHECK(!templ.IsEmpty());
   12824          22 :   LocalContext context;
   12825             :   v8::Local<v8::Function> fun =
   12826          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12827          11 :   GenerateSomeGarbage();
   12828          66 :   CHECK(context->Global()
   12829             :             ->Set(context.local(), v8_str("o"),
   12830             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12831             :             .FromJust());
   12832          22 :   v8::TryCatch try_catch(isolate);
   12833             :   CompileRun(
   12834             :       "o.foo = 17;"
   12835             :       "var receiver = {};"
   12836             :       "receiver.__proto__ = o;"
   12837             :       "var result = 0;"
   12838             :       "var saved_result = 0;"
   12839             :       "for (var i = 0; i < 100; i++) {"
   12840             :       "  result = receiver.method(41);"
   12841             :       "  if (i == 50) {"
   12842             :       "    saved_result = result;"
   12843             :       "    receiver = 333;"
   12844             :       "  }"
   12845             :       "}");
   12846          11 :   CHECK(try_catch.HasCaught());
   12847             :   // TODO(verwaest): Adjust message.
   12848          55 :   CHECK(
   12849             :       v8_str("TypeError: receiver.method is not a function")
   12850             :           ->Equals(
   12851             :               context.local(),
   12852             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12853             :           .FromJust());
   12854          66 :   CHECK_EQ(42, context->Global()
   12855             :                    ->Get(context.local(), v8_str("saved_result"))
   12856             :                    .ToLocalChecked()
   12857             :                    ->Int32Value(context.local())
   12858          11 :                    .FromJust());
   12859          11 : }
   12860             : 
   12861             : 
   12862       56690 : THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
   12863          11 :   v8::Isolate* isolate = CcTest::isolate();
   12864          11 :   v8::HandleScope scope(isolate);
   12865             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12866          11 :       v8::FunctionTemplate::New(isolate);
   12867             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12868             :       isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
   12869          22 :       v8::Signature::New(isolate, fun_templ));
   12870          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12871          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12872          11 :   fun_templ->SetHiddenPrototype(true);
   12873          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12874          11 :   CHECK(!templ.IsEmpty());
   12875          22 :   LocalContext context;
   12876             :   v8::Local<v8::Function> fun =
   12877          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12878          11 :   GenerateSomeGarbage();
   12879          66 :   CHECK(context->Global()
   12880             :             ->Set(context.local(), v8_str("o"),
   12881             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12882             :             .FromJust());
   12883          22 :   v8::TryCatch try_catch(isolate);
   12884             :   CompileRun(
   12885             :       "o.foo = 17;"
   12886             :       "var receiver = {};"
   12887             :       "receiver.__proto__ = o;"
   12888             :       "var result = 0;"
   12889             :       "var saved_result = 0;"
   12890             :       "for (var i = 0; i < 100; i++) {"
   12891             :       "  result = receiver.method(41);"
   12892             :       "  if (i == 50) {"
   12893             :       "    saved_result = result;"
   12894             :       "    receiver = Object.create(receiver);"
   12895             :       "  }"
   12896             :       "}");
   12897          11 :   CHECK(try_catch.HasCaught());
   12898          55 :   CHECK(
   12899             :       v8_str("TypeError: Illegal invocation")
   12900             :           ->Equals(
   12901             :               context.local(),
   12902             :               try_catch.Exception()->ToString(context.local()).ToLocalChecked())
   12903             :           .FromJust());
   12904          66 :   CHECK_EQ(42, context->Global()
   12905             :                    ->Get(context.local(), v8_str("saved_result"))
   12906             :                    .ToLocalChecked()
   12907             :                    ->Int32Value(context.local())
   12908          11 :                    .FromJust());
   12909          11 : }
   12910             : 
   12911             : 
   12912          24 : static void ThrowingGetter(Local<String> name,
   12913             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12914          24 :   ApiTestFuzzer::Fuzz();
   12915          24 :   info.GetIsolate()->ThrowException(Local<Value>());
   12916             :   info.GetReturnValue().SetUndefined();
   12917          24 : }
   12918             : 
   12919             : 
   12920       28343 : THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12921           6 :   LocalContext context;
   12922          12 :   HandleScope scope(context->GetIsolate());
   12923             : 
   12924           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   12925           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12926          12 :   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12927             : 
   12928           6 :   Local<Object> instance = templ->GetFunction(context.local())
   12929           6 :                                .ToLocalChecked()
   12930           6 :                                ->NewInstance(context.local())
   12931             :                                .ToLocalChecked();
   12932             : 
   12933           6 :   Local<Object> another = Object::New(context->GetIsolate());
   12934          12 :   CHECK(another->SetPrototype(context.local(), instance).FromJust());
   12935             : 
   12936             :   Local<Object> with_js_getter = CompileRun(
   12937             :       "o = {};\n"
   12938             :       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12939             :       "o\n").As<Object>();
   12940           6 :   CHECK(!with_js_getter.IsEmpty());
   12941             : 
   12942          12 :   TryCatch try_catch(context->GetIsolate());
   12943             : 
   12944             :   v8::MaybeLocal<Value> result =
   12945          12 :       instance->GetRealNamedProperty(context.local(), v8_str("f"));
   12946           6 :   CHECK(try_catch.HasCaught());
   12947           6 :   try_catch.Reset();
   12948           6 :   CHECK(result.IsEmpty());
   12949             : 
   12950             :   Maybe<PropertyAttribute> attr =
   12951          12 :       instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12952           6 :   CHECK(!try_catch.HasCaught());
   12953           6 :   CHECK(Just(None) == attr);
   12954             : 
   12955          12 :   result = another->GetRealNamedProperty(context.local(), v8_str("f"));
   12956           6 :   CHECK(try_catch.HasCaught());
   12957           6 :   try_catch.Reset();
   12958           6 :   CHECK(result.IsEmpty());
   12959             : 
   12960          12 :   attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12961           6 :   CHECK(!try_catch.HasCaught());
   12962           6 :   CHECK(Just(None) == attr);
   12963             : 
   12964             :   result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
   12965          12 :                                                          v8_str("f"));
   12966           6 :   CHECK(try_catch.HasCaught());
   12967           6 :   try_catch.Reset();
   12968           6 :   CHECK(result.IsEmpty());
   12969             : 
   12970             :   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
   12971          12 :       context.local(), v8_str("f"));
   12972           6 :   CHECK(!try_catch.HasCaught());
   12973           6 :   CHECK(Just(None) == attr);
   12974             : 
   12975          12 :   result = another->Get(context.local(), v8_str("f"));
   12976           6 :   CHECK(try_catch.HasCaught());
   12977           6 :   try_catch.Reset();
   12978           6 :   CHECK(result.IsEmpty());
   12979             : 
   12980          12 :   result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
   12981           6 :   CHECK(try_catch.HasCaught());
   12982           6 :   try_catch.Reset();
   12983           6 :   CHECK(result.IsEmpty());
   12984             : 
   12985             :   attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
   12986          12 :                                                         v8_str("f"));
   12987           6 :   CHECK(!try_catch.HasCaught());
   12988           6 :   CHECK(Just(None) == attr);
   12989             : 
   12990          12 :   result = with_js_getter->Get(context.local(), v8_str("f"));
   12991           6 :   CHECK(try_catch.HasCaught());
   12992           6 :   try_catch.Reset();
   12993           6 :   CHECK(result.IsEmpty());
   12994             : 
   12995             :   Local<Object> target = CompileRun("({})").As<Object>();
   12996           6 :   Local<Object> handler = CompileRun("({})").As<Object>();
   12997             :   Local<v8::Proxy> proxy =
   12998           6 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   12999             : 
   13000          12 :   result = target->GetRealNamedProperty(context.local(), v8_str("f"));
   13001           6 :   CHECK(!try_catch.HasCaught());
   13002           6 :   CHECK(result.IsEmpty());
   13003             : 
   13004          12 :   result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
   13005           6 :   CHECK(!try_catch.HasCaught());
   13006          12 :   CHECK(result.IsEmpty());
   13007           6 : }
   13008             : 
   13009             : 
   13010          30 : static void ThrowingCallbackWithTryCatch(
   13011          30 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13012          30 :   TryCatch try_catch(args.GetIsolate());
   13013             :   // Verboseness is important: it triggers message delivery which can call into
   13014             :   // external code.
   13015          30 :   try_catch.SetVerbose(true);
   13016             :   CompileRun("throw 'from JS';");
   13017          30 :   CHECK(try_catch.HasCaught());
   13018          30 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   13019          30 :   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   13020          30 : }
   13021             : 
   13022             : 
   13023             : static int call_depth;
   13024             : 
   13025             : 
   13026           6 : static void WithTryCatch(Local<Message> message, Local<Value> data) {
   13027           6 :   TryCatch try_catch(CcTest::isolate());
   13028           6 : }
   13029             : 
   13030             : 
   13031           6 : static void ThrowFromJS(Local<Message> message, Local<Value> data) {
   13032           6 :   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   13033           6 : }
   13034             : 
   13035             : 
   13036           6 : static void ThrowViaApi(Local<Message> message, Local<Value> data) {
   13037          12 :   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   13038           6 : }
   13039             : 
   13040             : 
   13041           6 : static void WebKitLike(Local<Message> message, Local<Value> data) {
   13042           6 :   Local<String> errorMessageString = message->Get();
   13043           6 :   CHECK(!errorMessageString.IsEmpty());
   13044           6 :   message->GetStackTrace();
   13045           6 :   message->GetScriptOrigin().ResourceName();
   13046           6 : }
   13047             : 
   13048             : 
   13049       28343 : THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   13050           6 :   LocalContext context;
   13051           6 :   v8::Isolate* isolate = context->GetIsolate();
   13052          12 :   HandleScope scope(isolate);
   13053             : 
   13054             :   Local<Function> func =
   13055           6 :       FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
   13056          18 :           ->GetFunction(context.local())
   13057           6 :           .ToLocalChecked();
   13058          30 :   CHECK(
   13059             :       context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
   13060             : 
   13061             :   MessageCallback callbacks[] = {nullptr, WebKitLike, ThrowViaApi, ThrowFromJS,
   13062           6 :                                  WithTryCatch};
   13063          36 :   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   13064          30 :     MessageCallback callback = callbacks[i];
   13065          30 :     if (callback != nullptr) {
   13066          24 :       isolate->AddMessageListener(callback);
   13067             :     }
   13068             :     // Some small number to control number of times message handler should
   13069             :     // throw an exception.
   13070          30 :     call_depth = 5;
   13071             :     ExpectFalse(
   13072             :         "var thrown = false;\n"
   13073             :         "try { func(); } catch(e) { thrown = true; }\n"
   13074             :         "thrown\n");
   13075          30 :     if (callback != nullptr) {
   13076          24 :       isolate->RemoveMessageListeners(callback);
   13077             :     }
   13078           6 :   }
   13079           6 : }
   13080             : 
   13081             : 
   13082           6 : static void ParentGetter(Local<String> name,
   13083             :                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   13084           6 :   ApiTestFuzzer::Fuzz();
   13085           6 :   info.GetReturnValue().Set(v8_num(1));
   13086           6 : }
   13087             : 
   13088             : 
   13089          18 : static void ChildGetter(Local<String> name,
   13090             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   13091          18 :   ApiTestFuzzer::Fuzz();
   13092          18 :   info.GetReturnValue().Set(v8_num(42));
   13093          18 : }
   13094             : 
   13095             : 
   13096       28343 : THREADED_TEST(Overriding) {
   13097           6 :   LocalContext context;
   13098           6 :   v8::Isolate* isolate = context->GetIsolate();
   13099          12 :   v8::HandleScope scope(isolate);
   13100             : 
   13101             :   // Parent template.
   13102           6 :   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   13103             :   Local<ObjectTemplate> parent_instance_templ =
   13104           6 :       parent_templ->InstanceTemplate();
   13105          12 :   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   13106             : 
   13107             :   // Template that inherits from the parent template.
   13108           6 :   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   13109             :   Local<ObjectTemplate> child_instance_templ =
   13110           6 :       child_templ->InstanceTemplate();
   13111           6 :   child_templ->Inherit(parent_templ);
   13112             :   // Override 'f'.  The child version of 'f' should get called for child
   13113             :   // instances.
   13114           6 :   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   13115             :   // Add 'g' twice.  The 'g' added last should get called for instances.
   13116           6 :   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   13117           6 :   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   13118             : 
   13119             :   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   13120             :   // so 'h' can be shadowed on the instance object.
   13121           6 :   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   13122             :   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, nullptr,
   13123          12 :                                  v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
   13124             : 
   13125             :   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   13126             :   // but the attribute does not have effect because it is duplicated with
   13127             :   // nullptr setter.
   13128             :   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, nullptr,
   13129             :                                     v8::Local<Value>(), v8::DEFAULT,
   13130           6 :                                     v8::ReadOnly);
   13131             : 
   13132             :   // Instantiate the child template.
   13133           6 :   Local<v8::Object> instance = child_templ->GetFunction(context.local())
   13134           6 :                                    .ToLocalChecked()
   13135           6 :                                    ->NewInstance(context.local())
   13136             :                                    .ToLocalChecked();
   13137             : 
   13138             :   // Check that the child function overrides the parent one.
   13139          30 :   CHECK(context->Global()
   13140             :             ->Set(context.local(), v8_str("o"), instance)
   13141             :             .FromJust());
   13142          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13143             :   // Check that the 'g' that was added last is hit.
   13144          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13145          12 :   value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
   13146          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13147             : 
   13148             :   // Check that 'h' cannot be shadowed.
   13149          12 :   value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
   13150          12 :   CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
   13151             : 
   13152             :   // Check that 'i' cannot be shadowed or changed.
   13153          12 :   value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
   13154          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   13155           6 : }
   13156             : 
   13157             : 
   13158          24 : static void ShouldThrowOnErrorGetter(
   13159             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   13160          24 :   ApiTestFuzzer::Fuzz();
   13161             :   v8::Isolate* isolate = info.GetIsolate();
   13162             :   Local<Boolean> should_throw_on_error =
   13163             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13164             :   info.GetReturnValue().Set(should_throw_on_error);
   13165          24 : }
   13166             : 
   13167             : 
   13168             : template <typename T>
   13169          24 : static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
   13170             :                                      const v8::PropertyCallbackInfo<T>& info) {
   13171          24 :   ApiTestFuzzer::Fuzz();
   13172             :   v8::Isolate* isolate = info.GetIsolate();
   13173          24 :   auto context = isolate->GetCurrentContext();
   13174             :   Local<Boolean> should_throw_on_error_value =
   13175             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13176         120 :   CHECK(context->Global()
   13177             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
   13178             :                   should_throw_on_error_value)
   13179             :             .FromJust());
   13180          24 : }
   13181             : 
   13182             : 
   13183       28343 : THREADED_TEST(AccessorShouldThrowOnError) {
   13184           6 :   LocalContext context;
   13185           6 :   v8::Isolate* isolate = context->GetIsolate();
   13186          12 :   v8::HandleScope scope(isolate);
   13187           6 :   Local<Object> global = context->Global();
   13188             : 
   13189           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13190           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   13191             :   instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
   13192          12 :                               ShouldThrowOnErrorSetter<void>);
   13193             : 
   13194           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13195           6 :                                    .ToLocalChecked()
   13196           6 :                                    ->NewInstance(context.local())
   13197             :                                    .ToLocalChecked();
   13198             : 
   13199          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   13200             : 
   13201             :   // SLOPPY mode
   13202          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13203           6 :   CHECK(value->IsFalse());
   13204          12 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   13205          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13206           6 :               .ToLocalChecked();
   13207           6 :   CHECK(value->IsFalse());
   13208             : 
   13209             :   // STRICT mode
   13210          12 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   13211           6 :   CHECK(value->IsFalse());
   13212          12 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   13213          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13214           6 :               .ToLocalChecked();
   13215          12 :   CHECK(value->IsTrue());
   13216           6 : }
   13217             : 
   13218             : 
   13219           0 : static void ShouldThrowOnErrorQuery(
   13220             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   13221           0 :   ApiTestFuzzer::Fuzz();
   13222             :   v8::Isolate* isolate = info.GetIsolate();
   13223             :   info.GetReturnValue().Set(v8::None);
   13224             : 
   13225           0 :   auto context = isolate->GetCurrentContext();
   13226             :   Local<Boolean> should_throw_on_error_value =
   13227             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13228           0 :   CHECK(context->Global()
   13229             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
   13230             :                   should_throw_on_error_value)
   13231             :             .FromJust());
   13232           0 : }
   13233             : 
   13234             : 
   13235          12 : static void ShouldThrowOnErrorDeleter(
   13236             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   13237          12 :   ApiTestFuzzer::Fuzz();
   13238             :   v8::Isolate* isolate = info.GetIsolate();
   13239             :   info.GetReturnValue().Set(v8::True(isolate));
   13240             : 
   13241          12 :   auto context = isolate->GetCurrentContext();
   13242             :   Local<Boolean> should_throw_on_error_value =
   13243             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13244          60 :   CHECK(context->Global()
   13245             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
   13246             :                   should_throw_on_error_value)
   13247             :             .FromJust());
   13248          12 : }
   13249             : 
   13250             : 
   13251          12 : static void ShouldThrowOnErrorPropertyEnumerator(
   13252             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
   13253          12 :   ApiTestFuzzer::Fuzz();
   13254             :   v8::Isolate* isolate = info.GetIsolate();
   13255          12 :   Local<v8::Array> names = v8::Array::New(isolate, 1);
   13256          36 :   CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
   13257             :   info.GetReturnValue().Set(names);
   13258             : 
   13259          12 :   auto context = isolate->GetCurrentContext();
   13260             :   Local<Boolean> should_throw_on_error_value =
   13261             :       Boolean::New(isolate, info.ShouldThrowOnError());
   13262          60 :   CHECK(context->Global()
   13263             :             ->Set(isolate->GetCurrentContext(),
   13264             :                   v8_str("should_throw_enumerator"),
   13265             :                   should_throw_on_error_value)
   13266             :             .FromJust());
   13267          12 : }
   13268             : 
   13269             : 
   13270       28343 : THREADED_TEST(InterceptorShouldThrowOnError) {
   13271           6 :   LocalContext context;
   13272           6 :   v8::Isolate* isolate = context->GetIsolate();
   13273          12 :   v8::HandleScope scope(isolate);
   13274           6 :   Local<Object> global = context->Global();
   13275             : 
   13276           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
   13277             :   v8::NamedPropertyHandlerConfiguration handler(
   13278             :       ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
   13279             :       ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
   13280             :       ShouldThrowOnErrorPropertyEnumerator);
   13281           6 :   interceptor_templ->SetHandler(handler);
   13282             : 
   13283             :   Local<v8::Object> instance =
   13284           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
   13285             : 
   13286          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   13287             : 
   13288             :   // SLOPPY mode
   13289          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   13290           6 :   CHECK(value->IsFalse());
   13291          12 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   13292          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13293           6 :               .ToLocalChecked();
   13294           6 :   CHECK(value->IsFalse());
   13295             : 
   13296          12 :   v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
   13297          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   13298           6 :               .ToLocalChecked();
   13299           6 :   CHECK(value->IsFalse());
   13300             : 
   13301             :   v8_compile("Object.getOwnPropertyNames(o)")
   13302           6 :       ->Run(context.local())
   13303           6 :       .ToLocalChecked();
   13304          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   13305           6 :               .ToLocalChecked();
   13306           6 :   CHECK(value->IsFalse());
   13307             : 
   13308             :   // STRICT mode
   13309          12 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   13310           6 :   CHECK(value->IsFalse());
   13311          12 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   13312          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   13313           6 :               .ToLocalChecked();
   13314           6 :   CHECK(value->IsTrue());
   13315             : 
   13316          12 :   v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
   13317          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   13318           6 :               .ToLocalChecked();
   13319           6 :   CHECK(value->IsTrue());
   13320             : 
   13321             :   v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
   13322           6 :       ->Run(context.local())
   13323           6 :       .ToLocalChecked();
   13324          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   13325           6 :               .ToLocalChecked();
   13326          12 :   CHECK(value->IsFalse());
   13327           6 : }
   13328             : 
   13329          55 : static void EmptyHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {}
   13330             : 
   13331       28342 : TEST(CallHandlerHasNoSideEffect) {
   13332           5 :   v8::Isolate* isolate = CcTest::isolate();
   13333           5 :   v8::HandleScope scope(isolate);
   13334          10 :   LocalContext context;
   13335             : 
   13336             :   // Function template with call handler.
   13337           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13338           5 :   templ->SetCallHandler(EmptyHandler);
   13339          30 :   CHECK(context->Global()
   13340             :             ->Set(context.local(), v8_str("f"),
   13341             :                   templ->GetFunction(context.local()).ToLocalChecked())
   13342             :             .FromJust());
   13343          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   13344          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   13345             : 
   13346             :   // Side-effect-free version.
   13347           5 :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
   13348             :   templ2->SetCallHandler(EmptyHandler, v8::Local<Value>(),
   13349           5 :                          v8::SideEffectType::kHasNoSideEffect);
   13350          30 :   CHECK(context->Global()
   13351             :             ->Set(context.local(), v8_str("f2"),
   13352             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   13353             :             .FromJust());
   13354           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   13355          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   13356           5 : }
   13357             : 
   13358       28342 : TEST(FunctionTemplateNewHasNoSideEffect) {
   13359           5 :   v8::Isolate* isolate = CcTest::isolate();
   13360           5 :   v8::HandleScope scope(isolate);
   13361          10 :   LocalContext context;
   13362             : 
   13363             :   // Function template with call handler.
   13364             :   Local<v8::FunctionTemplate> templ =
   13365           5 :       v8::FunctionTemplate::New(isolate, EmptyHandler);
   13366          35 :   CHECK(context->Global()
   13367             :             ->Set(context.local(), v8_str("f"),
   13368             :                   templ->GetFunction(context.local()).ToLocalChecked())
   13369             :             .FromJust());
   13370          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   13371          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   13372             : 
   13373             :   // Side-effect-free version.
   13374             :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(
   13375             :       isolate, EmptyHandler, v8::Local<Value>(), v8::Local<v8::Signature>(), 0,
   13376           5 :       v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
   13377          35 :   CHECK(context->Global()
   13378             :             ->Set(context.local(), v8_str("f2"),
   13379             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   13380             :             .FromJust());
   13381           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   13382          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   13383           5 : }
   13384             : 
   13385       28342 : TEST(FunctionTemplateNewWithCacheHasNoSideEffect) {
   13386           5 :   v8::Isolate* isolate = CcTest::isolate();
   13387           5 :   v8::HandleScope scope(isolate);
   13388          10 :   LocalContext context;
   13389             :   v8::Local<v8::Private> priv =
   13390           5 :       v8::Private::ForApi(isolate, v8_str("Foo#draft"));
   13391             : 
   13392             :   // Function template with call handler.
   13393             :   Local<v8::FunctionTemplate> templ =
   13394           5 :       v8::FunctionTemplate::NewWithCache(isolate, EmptyHandler, priv);
   13395          35 :   CHECK(context->Global()
   13396             :             ->Set(context.local(), v8_str("f"),
   13397             :                   templ->GetFunction(context.local()).ToLocalChecked())
   13398             :             .FromJust());
   13399          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   13400          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   13401             : 
   13402             :   // Side-effect-free version.
   13403             :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::NewWithCache(
   13404             :       isolate, EmptyHandler, priv, v8::Local<Value>(),
   13405           5 :       v8::Local<v8::Signature>(), 0, v8::SideEffectType::kHasNoSideEffect);
   13406          35 :   CHECK(context->Global()
   13407             :             ->Set(context.local(), v8_str("f2"),
   13408             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   13409             :             .FromJust());
   13410           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   13411          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   13412           5 : }
   13413             : 
   13414       28342 : TEST(FunctionNewHasNoSideEffect) {
   13415           5 :   v8::Isolate* isolate = CcTest::isolate();
   13416           5 :   v8::HandleScope scope(isolate);
   13417          10 :   LocalContext context;
   13418             : 
   13419             :   // Function with side-effect.
   13420             :   Local<Function> func =
   13421          10 :       Function::New(context.local(), EmptyHandler).ToLocalChecked();
   13422          25 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func).FromJust());
   13423          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   13424          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   13425             : 
   13426             :   // Side-effect-free version.
   13427             :   Local<Function> func2 =
   13428             :       Function::New(context.local(), EmptyHandler, Local<Value>(), 0,
   13429             :                     v8::ConstructorBehavior::kAllow,
   13430          10 :                     v8::SideEffectType::kHasNoSideEffect)
   13431           5 :           .ToLocalChecked();
   13432          25 :   CHECK(
   13433             :       context->Global()->Set(context.local(), v8_str("f2"), func2).FromJust());
   13434           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   13435          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   13436           5 : }
   13437             : 
   13438             : // These handlers instantiate a function the embedder considers safe in some
   13439             : // cases (e.g. "building object wrappers"), but those functions themselves were
   13440             : // not explicitly marked as side-effect-free.
   13441           5 : static void DefaultConstructHandler(
   13442           5 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   13443           5 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   13444             :   v8::Context::Scope context_scope(context);
   13445           5 :   v8::MaybeLocal<v8::Object> instance = Function::New(context, EmptyHandler)
   13446           5 :                                             .ToLocalChecked()
   13447           5 :                                             ->NewInstance(context, 0, nullptr);
   13448             :   USE(instance);
   13449           5 : }
   13450             : 
   13451          10 : static void NoSideEffectConstructHandler(
   13452          10 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   13453          10 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   13454             :   v8::Context::Scope context_scope(context);
   13455             :   v8::MaybeLocal<v8::Object> instance =
   13456          10 :       Function::New(context, EmptyHandler)
   13457          10 :           .ToLocalChecked()
   13458             :           ->NewInstanceWithSideEffectType(context, 0, nullptr,
   13459          10 :                                           v8::SideEffectType::kHasNoSideEffect);
   13460             :   USE(instance);
   13461          10 : }
   13462             : 
   13463           5 : static void NoSideEffectAndSideEffectConstructHandler(
   13464           5 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   13465           5 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   13466             :   v8::Context::Scope context_scope(context);
   13467             :   // Constructs an instance in a side-effect-free way, followed by another with
   13468             :   // side effects.
   13469             :   v8::MaybeLocal<v8::Object> instance =
   13470           5 :       Function::New(context, EmptyHandler)
   13471           5 :           .ToLocalChecked()
   13472             :           ->NewInstanceWithSideEffectType(context, 0, nullptr,
   13473           5 :                                           v8::SideEffectType::kHasNoSideEffect);
   13474           5 :   v8::MaybeLocal<v8::Object> instance2 = Function::New(context, EmptyHandler)
   13475           5 :                                              .ToLocalChecked()
   13476           5 :                                              ->NewInstance(context, 0, nullptr);
   13477             :   USE(instance);
   13478             :   USE(instance2);
   13479           5 : }
   13480             : 
   13481       28342 : TEST(FunctionNewInstanceHasNoSideEffect) {
   13482           5 :   v8::Isolate* isolate = CcTest::isolate();
   13483           5 :   v8::HandleScope scope(isolate);
   13484          10 :   LocalContext context;
   13485             : 
   13486             :   // A whitelisted function that creates a new object with both side-effect
   13487             :   // free/full instantiations. Should throw.
   13488             :   Local<Function> func0 =
   13489             :       Function::New(context.local(), NoSideEffectAndSideEffectConstructHandler,
   13490             :                     Local<Value>(), 0, v8::ConstructorBehavior::kAllow,
   13491          10 :                     v8::SideEffectType::kHasNoSideEffect)
   13492           5 :           .ToLocalChecked();
   13493          25 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func0).FromJust());
   13494          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   13495             : 
   13496             :   // A whitelisted function that creates a new object. Should throw.
   13497             :   Local<Function> func =
   13498             :       Function::New(context.local(), DefaultConstructHandler, Local<Value>(), 0,
   13499             :                     v8::ConstructorBehavior::kAllow,
   13500          10 :                     v8::SideEffectType::kHasNoSideEffect)
   13501           5 :           .ToLocalChecked();
   13502          25 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func).FromJust());
   13503          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   13504             : 
   13505             :   // A whitelisted function that creates a new object with explicit intent to
   13506             :   // have no side-effects (e.g. building an "object wrapper"). Should not throw.
   13507             :   Local<Function> func2 =
   13508             :       Function::New(context.local(), NoSideEffectConstructHandler,
   13509             :                     Local<Value>(), 0, v8::ConstructorBehavior::kAllow,
   13510          10 :                     v8::SideEffectType::kHasNoSideEffect)
   13511           5 :           .ToLocalChecked();
   13512          25 :   CHECK(
   13513             :       context->Global()->Set(context.local(), v8_str("f2"), func2).FromJust());
   13514           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   13515             : 
   13516             :   // Check that side effect skipping did not leak outside to future evaluations.
   13517             :   Local<Function> func3 =
   13518          10 :       Function::New(context.local(), EmptyHandler).ToLocalChecked();
   13519          25 :   CHECK(
   13520             :       context->Global()->Set(context.local(), v8_str("f3"), func3).FromJust());
   13521          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f3()"), true).IsEmpty());
   13522             : 
   13523             :   // Check that using side effect free NewInstance works in normal evaluation
   13524             :   // (without throwOnSideEffect).
   13525          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), false).ToLocalChecked();
   13526           5 : }
   13527             : 
   13528       28342 : TEST(CallHandlerAsFunctionHasNoSideEffectNotSupported) {
   13529           5 :   v8::Isolate* isolate = CcTest::isolate();
   13530           5 :   v8::HandleScope scope(isolate);
   13531          10 :   LocalContext context;
   13532             : 
   13533             :   // Object template with call as function handler.
   13534           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   13535           5 :   templ->SetCallAsFunctionHandler(EmptyHandler);
   13536           5 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   13537          25 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   13538          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj()"), true).IsEmpty());
   13539             : 
   13540             :   // Side-effect-free version is not supported.
   13541             :   i::FunctionTemplateInfo cons = i::FunctionTemplateInfo::cast(
   13542          10 :       v8::Utils::OpenHandle(*templ)->constructor());
   13543           5 :   i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
   13544             :   i::CallHandlerInfo handler_info =
   13545          10 :       i::CallHandlerInfo::cast(cons->GetInstanceCallHandler());
   13546           5 :   CHECK(!handler_info->IsSideEffectFreeCallHandlerInfo());
   13547             :   handler_info->set_map(
   13548           5 :       i::ReadOnlyRoots(heap).side_effect_free_call_handler_info_map());
   13549          15 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj()"), true).IsEmpty());
   13550           5 : }
   13551             : 
   13552          12 : static void IsConstructHandler(
   13553             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   13554          12 :   ApiTestFuzzer::Fuzz();
   13555             :   args.GetReturnValue().Set(args.IsConstructCall());
   13556          12 : }
   13557             : 
   13558             : 
   13559       28343 : THREADED_TEST(IsConstructCall) {
   13560           6 :   v8::Isolate* isolate = CcTest::isolate();
   13561           6 :   v8::HandleScope scope(isolate);
   13562             : 
   13563             :   // Function template with call handler.
   13564           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13565           6 :   templ->SetCallHandler(IsConstructHandler);
   13566             : 
   13567          12 :   LocalContext context;
   13568             : 
   13569          36 :   CHECK(context->Global()
   13570             :             ->Set(context.local(), v8_str("f"),
   13571             :                   templ->GetFunction(context.local()).ToLocalChecked())
   13572             :             .FromJust());
   13573          12 :   Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
   13574           6 :   CHECK(!value->BooleanValue(isolate));
   13575          12 :   value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
   13576          12 :   CHECK(value->BooleanValue(isolate));
   13577           6 : }
   13578             : 
   13579          48 : static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13580          24 :   ApiTestFuzzer::Fuzz();
   13581             :   args.GetReturnValue().Set(args.NewTarget());
   13582          24 : }
   13583             : 
   13584       28343 : THREADED_TEST(NewTargetHandler) {
   13585           6 :   v8::Isolate* isolate = CcTest::isolate();
   13586           6 :   v8::HandleScope scope(isolate);
   13587             : 
   13588             :   // Function template with call handler.
   13589           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13590           6 :   templ->SetCallHandler(NewTargetHandler);
   13591             : 
   13592          12 :   LocalContext context;
   13593             : 
   13594             :   Local<Function> function =
   13595           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   13596          30 :   CHECK(context->Global()
   13597             :             ->Set(context.local(), v8_str("f"), function)
   13598             :             .FromJust());
   13599             :   Local<Value> value = CompileRun("f()");
   13600           6 :   CHECK(value->IsUndefined());
   13601             :   value = CompileRun("new f()");
   13602           6 :   CHECK(value->IsFunction());
   13603           6 :   CHECK(value == function);
   13604             :   Local<Value> subclass = CompileRun("var g = class extends f { }; g");
   13605           6 :   CHECK(subclass->IsFunction());
   13606             :   value = CompileRun("new g()");
   13607           6 :   CHECK(value->IsFunction());
   13608           6 :   CHECK(value == subclass);
   13609             :   value = CompileRun("Reflect.construct(f, [], Array)");
   13610           6 :   CHECK(value->IsFunction());
   13611          30 :   CHECK(value ==
   13612             :         context->Global()
   13613             :             ->Get(context.local(), v8_str("Array"))
   13614           6 :             .ToLocalChecked());
   13615           6 : }
   13616             : 
   13617       28343 : THREADED_TEST(ObjectProtoToString) {
   13618           6 :   v8::Isolate* isolate = CcTest::isolate();
   13619           6 :   v8::HandleScope scope(isolate);
   13620           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13621           6 :   templ->SetClassName(v8_str("MyClass"));
   13622             : 
   13623          12 :   LocalContext context;
   13624             : 
   13625           6 :   Local<String> customized_tostring = v8_str("customized toString");
   13626             : 
   13627             :   // Replace Object.prototype.toString
   13628             :   v8_compile(
   13629             :       "Object.prototype.toString = function() {"
   13630             :       "  return 'customized toString';"
   13631             :       "}")
   13632           6 :       ->Run(context.local())
   13633           6 :       .ToLocalChecked();
   13634             : 
   13635             :   // Normal ToString call should call replaced Object.prototype.toString
   13636           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13637           6 :                                    .ToLocalChecked()
   13638           6 :                                    ->NewInstance(context.local())
   13639             :                                    .ToLocalChecked();
   13640           6 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13641          18 :   CHECK(value->IsString() &&
   13642             :         value->Equals(context.local(), customized_tostring).FromJust());
   13643             : 
   13644             :   // ObjectProtoToString should not call replace toString function.
   13645           6 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13646          18 :   CHECK(value->IsString() &&
   13647             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13648             : 
   13649             :   // Check global
   13650             :   value =
   13651          24 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13652          18 :   CHECK(value->IsString() &&
   13653             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13654             : 
   13655             :   // Check ordinary object
   13656             :   Local<Value> object =
   13657          12 :       v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
   13658             :   value = object.As<v8::Object>()
   13659           6 :               ->ObjectProtoToString(context.local())
   13660           6 :               .ToLocalChecked();
   13661          18 :   CHECK(value->IsString() &&
   13662           6 :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13663           6 : }
   13664             : 
   13665             : 
   13666       28342 : TEST(ObjectProtoToStringES6) {
   13667           5 :   LocalContext context;
   13668           5 :   v8::Isolate* isolate = CcTest::isolate();
   13669          10 :   v8::HandleScope scope(isolate);
   13670           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13671           5 :   templ->SetClassName(v8_str("MyClass"));
   13672             : 
   13673           5 :   Local<String> customized_tostring = v8_str("customized toString");
   13674             : 
   13675             :   // Replace Object.prototype.toString
   13676             :   CompileRun(
   13677             :       "Object.prototype.toString = function() {"
   13678             :       "  return 'customized toString';"
   13679             :       "}");
   13680             : 
   13681             :   // Normal ToString call should call replaced Object.prototype.toString
   13682           5 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13683           5 :                                    .ToLocalChecked()
   13684           5 :                                    ->NewInstance(context.local())
   13685             :                                    .ToLocalChecked();
   13686           5 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13687          15 :   CHECK(value->IsString() &&
   13688             :         value->Equals(context.local(), customized_tostring).FromJust());
   13689             : 
   13690             :   // ObjectProtoToString should not call replace toString function.
   13691           5 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13692          15 :   CHECK(value->IsString() &&
   13693             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13694             : 
   13695             :   // Check global
   13696             :   value =
   13697          20 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13698          15 :   CHECK(value->IsString() &&
   13699             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13700             : 
   13701             :   // Check ordinary object
   13702             :   Local<Value> object = CompileRun("new Object()");
   13703             :   value = object.As<v8::Object>()
   13704           5 :               ->ObjectProtoToString(context.local())
   13705           5 :               .ToLocalChecked();
   13706          15 :   CHECK(value->IsString() &&
   13707             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13708             : 
   13709             :   // Check that ES6 semantics using @@toStringTag work
   13710           5 :   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
   13711             : 
   13712             : #define TEST_TOSTRINGTAG(type, tag, expected)                              \
   13713             :   do {                                                                     \
   13714             :     object = CompileRun("new " #type "()");                                \
   13715             :     CHECK(object.As<v8::Object>()                                          \
   13716             :               ->Set(context.local(), toStringTag, v8_str(#tag))            \
   13717             :               .FromJust());                                                \
   13718             :     value = object.As<v8::Object>()                                        \
   13719             :                 ->ObjectProtoToString(context.local())                     \
   13720             :                 .ToLocalChecked();                                         \
   13721             :     CHECK(value->IsString() &&                                             \
   13722             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13723             :               .FromJust());                                                \
   13724             :   } while (false)
   13725             : 
   13726          30 :   TEST_TOSTRINGTAG(Array, Object, Object);
   13727          30 :   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
   13728          30 :   TEST_TOSTRINGTAG(Object, Array, Array);
   13729          30 :   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
   13730          30 :   TEST_TOSTRINGTAG(Object, Date, Date);
   13731          30 :   TEST_TOSTRINGTAG(Object, Error, Error);
   13732          30 :   TEST_TOSTRINGTAG(Object, Function, Function);
   13733          30 :   TEST_TOSTRINGTAG(Object, Number, Number);
   13734          30 :   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
   13735          30 :   TEST_TOSTRINGTAG(Object, String, String);
   13736          30 :   TEST_TOSTRINGTAG(Object, Foo, Foo);
   13737             : 
   13738             : #undef TEST_TOSTRINGTAG
   13739             : 
   13740             :   Local<v8::RegExp> valueRegExp =
   13741           5 :       v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
   13742           5 :           .ToLocalChecked();
   13743           5 :   Local<Value> valueNumber = v8_num(123);
   13744           5 :   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
   13745             :   Local<v8::Function> valueFunction =
   13746             :       CompileRun("(function fn() {})").As<v8::Function>();
   13747           5 :   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
   13748           5 :   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
   13749           5 :   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
   13750             : 
   13751             : #define TEST_TOSTRINGTAG(type, tagValue, expected)                         \
   13752             :   do {                                                                     \
   13753             :     object = CompileRun("new " #type "()");                                \
   13754             :     CHECK(object.As<v8::Object>()                                          \
   13755             :               ->Set(context.local(), toStringTag, tagValue)                \
   13756             :               .FromJust());                                                \
   13757             :     value = object.As<v8::Object>()                                        \
   13758             :                 ->ObjectProtoToString(context.local())                     \
   13759             :                 .ToLocalChecked();                                         \
   13760             :     CHECK(value->IsString() &&                                             \
   13761             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13762             :               .FromJust());                                                \
   13763             :   } while (false)
   13764             : 
   13765             : #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
   13766             :   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
   13767             :   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
   13768             :   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
   13769             :   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
   13770             :   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
   13771             :   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
   13772             : 
   13773             :   // Test non-String-valued @@toStringTag
   13774         150 :   TEST_TOSTRINGTAG_TYPES(valueRegExp);
   13775         150 :   TEST_TOSTRINGTAG_TYPES(valueNumber);
   13776         150 :   TEST_TOSTRINGTAG_TYPES(valueSymbol);
   13777         150 :   TEST_TOSTRINGTAG_TYPES(valueFunction);
   13778         150 :   TEST_TOSTRINGTAG_TYPES(valueObject);
   13779         150 :   TEST_TOSTRINGTAG_TYPES(valueNull);
   13780         150 :   TEST_TOSTRINGTAG_TYPES(valueUndef);
   13781             : 
   13782             : #undef TEST_TOSTRINGTAG
   13783             : #undef TEST_TOSTRINGTAG_TYPES
   13784             : 
   13785             :   // @@toStringTag getter throws
   13786           5 :   Local<Value> obj = v8::Object::New(isolate);
   13787             :   obj.As<v8::Object>()
   13788          10 :       ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
   13789          10 :       .FromJust();
   13790             :   {
   13791           5 :     TryCatch try_catch(isolate);
   13792          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13793           5 :     CHECK(try_catch.HasCaught());
   13794             :   }
   13795             : 
   13796             :   // @@toStringTag getter does not throw
   13797           5 :   obj = v8::Object::New(isolate);
   13798             :   obj.As<v8::Object>()
   13799             :       ->SetAccessor(context.local(), toStringTag,
   13800          15 :                     SymbolAccessorGetterReturnsDefault, nullptr, v8_str("Test"))
   13801          10 :       .FromJust();
   13802             :   {
   13803           5 :     TryCatch try_catch(isolate);
   13804             :     value = obj.As<v8::Object>()
   13805           5 :                 ->ObjectProtoToString(context.local())
   13806           5 :                 .ToLocalChecked();
   13807          15 :     CHECK(value->IsString() &&
   13808             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13809           5 :     CHECK(!try_catch.HasCaught());
   13810             :   }
   13811             : 
   13812             :   // JS @@toStringTag value
   13813             :   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
   13814             :   {
   13815           5 :     TryCatch try_catch(isolate);
   13816             :     value = obj.As<v8::Object>()
   13817           5 :                 ->ObjectProtoToString(context.local())
   13818           5 :                 .ToLocalChecked();
   13819          15 :     CHECK(value->IsString() &&
   13820             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13821           5 :     CHECK(!try_catch.HasCaught());
   13822             :   }
   13823             : 
   13824             :   // JS @@toStringTag getter throws
   13825             :   obj = CompileRun(
   13826             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13827             :       "  get: function() { throw 'Test'; }"
   13828             :       "}); obj");
   13829             :   {
   13830           5 :     TryCatch try_catch(isolate);
   13831          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13832           5 :     CHECK(try_catch.HasCaught());
   13833             :   }
   13834             : 
   13835             :   // JS @@toStringTag getter does not throw
   13836             :   obj = CompileRun(
   13837             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13838             :       "  get: function() { return 'Test'; }"
   13839             :       "}); obj");
   13840             :   {
   13841           5 :     TryCatch try_catch(isolate);
   13842             :     value = obj.As<v8::Object>()
   13843           5 :                 ->ObjectProtoToString(context.local())
   13844           5 :                 .ToLocalChecked();
   13845          15 :     CHECK(value->IsString() &&
   13846             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13847           5 :     CHECK(!try_catch.HasCaught());
   13848           5 :   }
   13849           5 : }
   13850             : 
   13851             : 
   13852       28343 : THREADED_TEST(ObjectGetConstructorName) {
   13853           6 :   v8::Isolate* isolate = CcTest::isolate();
   13854           6 :   LocalContext context;
   13855          12 :   v8::HandleScope scope(isolate);
   13856             :   v8_compile(
   13857             :       "function Parent() {};"
   13858             :       "function Child() {};"
   13859             :       "Child.prototype = new Parent();"
   13860             :       "Child.prototype.constructor = Child;"
   13861             :       "var outer = { inner: (0, function() { }) };"
   13862             :       "var p = new Parent();"
   13863             :       "var c = new Child();"
   13864             :       "var x = new outer.inner();"
   13865             :       "var proto = Child.prototype;")
   13866           6 :       ->Run(context.local())
   13867           6 :       .ToLocalChecked();
   13868             : 
   13869             :   Local<v8::Value> p =
   13870          30 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13871          30 :   CHECK(p->IsObject() &&
   13872             :         p->ToObject(context.local())
   13873             :             .ToLocalChecked()
   13874             :             ->GetConstructorName()
   13875             :             ->Equals(context.local(), v8_str("Parent"))
   13876             :             .FromJust());
   13877             : 
   13878             :   Local<v8::Value> c =
   13879          30 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13880          30 :   CHECK(c->IsObject() &&
   13881             :         c->ToObject(context.local())
   13882             :             .ToLocalChecked()
   13883             :             ->GetConstructorName()
   13884             :             ->Equals(context.local(), v8_str("Child"))
   13885             :             .FromJust());
   13886             : 
   13887             :   Local<v8::Value> x =
   13888          30 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
   13889          30 :   CHECK(x->IsObject() &&
   13890             :         x->ToObject(context.local())
   13891             :             .ToLocalChecked()
   13892             :             ->GetConstructorName()
   13893             :             ->Equals(context.local(), v8_str("outer.inner"))
   13894             :             .FromJust());
   13895             : 
   13896             :   Local<v8::Value> child_prototype =
   13897          30 :       context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
   13898          30 :   CHECK(child_prototype->IsObject() &&
   13899             :         child_prototype->ToObject(context.local())
   13900             :             .ToLocalChecked()
   13901             :             ->GetConstructorName()
   13902             :             ->Equals(context.local(), v8_str("Parent"))
   13903           6 :             .FromJust());
   13904           6 : }
   13905             : 
   13906             : 
   13907       28343 : THREADED_TEST(SubclassGetConstructorName) {
   13908           6 :   v8::Isolate* isolate = CcTest::isolate();
   13909           6 :   LocalContext context;
   13910          12 :   v8::HandleScope scope(isolate);
   13911             :   v8_compile(
   13912             :       "\"use strict\";"
   13913             :       "class Parent {}"
   13914             :       "class Child extends Parent {}"
   13915             :       "var p = new Parent();"
   13916             :       "var c = new Child();")
   13917           6 :       ->Run(context.local())
   13918           6 :       .ToLocalChecked();
   13919             : 
   13920             :   Local<v8::Value> p =
   13921          30 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13922          30 :   CHECK(p->IsObject() &&
   13923             :         p->ToObject(context.local())
   13924             :             .ToLocalChecked()
   13925             :             ->GetConstructorName()
   13926             :             ->Equals(context.local(), v8_str("Parent"))
   13927             :             .FromJust());
   13928             : 
   13929             :   Local<v8::Value> c =
   13930          30 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13931          30 :   CHECK(c->IsObject() &&
   13932             :         c->ToObject(context.local())
   13933             :             .ToLocalChecked()
   13934             :             ->GetConstructorName()
   13935             :             ->Equals(context.local(), v8_str("Child"))
   13936           6 :             .FromJust());
   13937           6 : }
   13938             : 
   13939             : 
   13940             : bool ApiTestFuzzer::fuzzing_ = false;
   13941       28337 : v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13942             : int ApiTestFuzzer::active_tests_;
   13943             : int ApiTestFuzzer::tests_being_run_;
   13944             : int ApiTestFuzzer::current_;
   13945             : 
   13946             : 
   13947             : // We are in a callback and want to switch to another thread (if we
   13948             : // are currently running the thread fuzzing test).
   13949      470743 : void ApiTestFuzzer::Fuzz() {
   13950      941486 :   if (!fuzzing_) return;
   13951       77218 :   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13952       77218 :   test->ContextSwitch();
   13953             : }
   13954             : 
   13955             : 
   13956             : // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13957             : // not start immediately.
   13958       77698 : bool ApiTestFuzzer::NextThread() {
   13959       77698 :   int test_position = GetNextTestNumber();
   13960       77698 :   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13961       77698 :   if (test_position == current_) {
   13962             :     if (kLogThreading)
   13963             :       printf("Stay with %s\n", test_name);
   13964             :     return false;
   13965             :   }
   13966             :   if (kLogThreading) {
   13967             :     printf("Switch from %s to %s\n",
   13968             :            test_name,
   13969             :            RegisterThreadedTest::nth(test_position)->name());
   13970             :   }
   13971       23643 :   current_ = test_position;
   13972       23643 :   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13973       23643 :   return true;
   13974             : }
   13975             : 
   13976             : 
   13977         480 : void ApiTestFuzzer::Run() {
   13978             :   // When it is our turn...
   13979         480 :   gate_.Wait();
   13980             :   {
   13981             :     // ... get the V8 lock and start running the test.
   13982         480 :     v8::Locker locker(CcTest::isolate());
   13983         480 :     CallTest();
   13984             :   }
   13985             :   // This test finished.
   13986         480 :   active_ = false;
   13987         480 :   active_tests_--;
   13988             :   // If it was the last then signal that fact.
   13989         480 :   if (active_tests_ == 0) {
   13990           8 :     all_tests_done_.Signal();
   13991             :   } else {
   13992             :     // Otherwise select a new test and start that.
   13993         472 :     NextThread();
   13994             :   }
   13995         480 : }
   13996             : 
   13997             : 
   13998             : static unsigned linear_congruential_generator;
   13999             : 
   14000             : 
   14001           8 : void ApiTestFuzzer::SetUp(PartOfTest part) {
   14002           8 :   linear_congruential_generator = i::FLAG_testing_prng_seed;
   14003           8 :   fuzzing_ = true;
   14004             :   int count = RegisterThreadedTest::count();
   14005           8 :   int start =  count * part / (LAST_PART + 1);
   14006           8 :   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   14007           8 :   active_tests_ = tests_being_run_ = end - start + 1;
   14008         488 :   for (int i = 0; i < tests_being_run_; i++) {
   14009         480 :     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   14010             :   }
   14011         480 :   for (int i = 0; i < active_tests_; i++) {
   14012         480 :     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   14013             :   }
   14014           8 : }
   14015             : 
   14016             : 
   14017             : static void CallTestNumber(int test_number) {
   14018         480 :   (RegisterThreadedTest::nth(test_number)->callback())();
   14019             : }
   14020             : 
   14021             : 
   14022           0 : void ApiTestFuzzer::RunAllTests() {
   14023             :   // Set off the first test.
   14024           8 :   current_ = -1;
   14025           8 :   NextThread();
   14026             :   // Wait till they are all done.
   14027           8 :   all_tests_done_.Wait();
   14028           0 : }
   14029             : 
   14030             : 
   14031       77698 : int ApiTestFuzzer::GetNextTestNumber() {
   14032             :   int next_test;
   14033     3251552 :   do {
   14034     3251552 :     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   14035     3251552 :     linear_congruential_generator *= 1664525u;
   14036     3251552 :     linear_congruential_generator += 1013904223u;
   14037     3251552 :   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   14038       77698 :   return next_test;
   14039             : }
   14040             : 
   14041             : 
   14042       77218 : void ApiTestFuzzer::ContextSwitch() {
   14043             :   // If the new thread is the same as the current thread there is nothing to do.
   14044       77218 :   if (NextThread()) {
   14045             :     // Now it can start.
   14046       23163 :     v8::Unlocker unlocker(CcTest::isolate());
   14047             :     // Wait till someone starts us again.
   14048       23163 :     gate_.Wait();
   14049             :     // And we're off.
   14050             :   }
   14051       77218 : }
   14052             : 
   14053             : 
   14054           8 : void ApiTestFuzzer::TearDown() {
   14055           8 :   fuzzing_ = false;
   14056        7696 :   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   14057        3840 :     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   14058        3840 :     if (fuzzer != nullptr) fuzzer->Join();
   14059             :   }
   14060           8 : }
   14061             : 
   14062         480 : void ApiTestFuzzer::CallTest() {
   14063         480 :   v8::Isolate::Scope scope(CcTest::isolate());
   14064             :   if (kLogThreading)
   14065             :     printf("Start test %s #%d\n",
   14066             :            RegisterThreadedTest::nth(test_number_)->name(), test_number_);
   14067         480 :   CallTestNumber(test_number_);
   14068             :   if (kLogThreading)
   14069             :     printf("End test %s #%d\n", RegisterThreadedTest::nth(test_number_)->name(),
   14070             :            test_number_);
   14071         480 : }
   14072             : 
   14073             : #define THREADING_TEST(INDEX, NAME)            \
   14074             :   TEST(Threading##INDEX) {                     \
   14075             :     ApiTestFuzzer::SetUp(ApiTestFuzzer::NAME); \
   14076             :     ApiTestFuzzer::RunAllTests();              \
   14077             :     ApiTestFuzzer::TearDown();                 \
   14078             :   }
   14079             : 
   14080       28339 : THREADING_TEST(1, FIRST_PART)
   14081       28339 : THREADING_TEST(2, SECOND_PART)
   14082       28339 : THREADING_TEST(3, THIRD_PART)
   14083       28339 : THREADING_TEST(4, FOURTH_PART)
   14084       28339 : THREADING_TEST(5, FIFTH_PART)
   14085       28339 : THREADING_TEST(6, SIXTH_PART)
   14086       28339 : THREADING_TEST(7, SEVENTH_PART)
   14087       28339 : THREADING_TEST(8, EIGHTH_PART)
   14088             : 
   14089             : #undef THREADING_TEST
   14090             : 
   14091          10 : static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   14092             :   v8::Isolate* isolate = args.GetIsolate();
   14093           5 :   CHECK(v8::Locker::IsLocked(isolate));
   14094           5 :   ApiTestFuzzer::Fuzz();
   14095             :   v8::Unlocker unlocker(isolate);
   14096             :   const char* code = "throw 7;";
   14097             :   {
   14098             :     v8::Locker nested_locker(isolate);
   14099          10 :     v8::HandleScope scope(isolate);
   14100             :     v8::Local<Value> exception;
   14101             :     {
   14102           5 :       v8::TryCatch try_catch(isolate);
   14103             :       v8::Local<Value> value = CompileRun(code);
   14104           5 :       CHECK(value.IsEmpty());
   14105           5 :       CHECK(try_catch.HasCaught());
   14106             :       // Make sure to wrap the exception in a new handle because
   14107             :       // the handle returned from the TryCatch is destroyed
   14108             :       // when the TryCatch is destroyed.
   14109          10 :       exception = Local<Value>::New(isolate, try_catch.Exception());
   14110             :     }
   14111          10 :     args.GetIsolate()->ThrowException(exception);
   14112           5 :   }
   14113           5 : }
   14114             : 
   14115             : 
   14116          15 : static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   14117           5 :   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   14118           5 :   ApiTestFuzzer::Fuzz();
   14119           5 :   v8::Unlocker unlocker(CcTest::isolate());
   14120             :   const char* code = "throw 7;";
   14121             :   {
   14122           5 :     v8::Locker nested_locker(CcTest::isolate());
   14123          10 :     v8::HandleScope scope(args.GetIsolate());
   14124             :     v8::Local<Value> value = CompileRun(code);
   14125           5 :     CHECK(value.IsEmpty());
   14126          10 :     args.GetReturnValue().Set(v8_str("foo"));
   14127           5 :   }
   14128           5 : }
   14129             : 
   14130             : 
   14131             : // These are locking tests that don't need to be run again
   14132             : // as part of the locking aggregation tests.
   14133       28342 : TEST(NestedLockers) {
   14134           5 :   v8::Isolate* isolate = CcTest::isolate();
   14135             :   v8::Locker locker(isolate);
   14136           5 :   CHECK(v8::Locker::IsLocked(isolate));
   14137          10 :   LocalContext env;
   14138          10 :   v8::HandleScope scope(env->GetIsolate());
   14139             :   Local<v8::FunctionTemplate> fun_templ =
   14140           5 :       v8::FunctionTemplate::New(isolate, ThrowInJS);
   14141          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   14142          25 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   14143             :   Local<Script> script = v8_compile("(function () {"
   14144             :                                     "  try {"
   14145             :                                     "    throw_in_js();"
   14146             :                                     "    return 42;"
   14147             :                                     "  } catch (e) {"
   14148             :                                     "    return e * 13;"
   14149             :                                     "  }"
   14150             :                                     "})();");
   14151          15 :   CHECK_EQ(91, script->Run(env.local())
   14152             :                    .ToLocalChecked()
   14153             :                    ->Int32Value(env.local())
   14154           5 :                    .FromJust());
   14155           5 : }
   14156             : 
   14157             : 
   14158             : // These are locking tests that don't need to be run again
   14159             : // as part of the locking aggregation tests.
   14160       28342 : TEST(NestedLockersNoTryCatch) {
   14161           5 :   v8::Locker locker(CcTest::isolate());
   14162          10 :   LocalContext env;
   14163          10 :   v8::HandleScope scope(env->GetIsolate());
   14164             :   Local<v8::FunctionTemplate> fun_templ =
   14165           5 :       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   14166          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   14167          25 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   14168             :   Local<Script> script = v8_compile("(function () {"
   14169             :                                     "  try {"
   14170             :                                     "    throw_in_js();"
   14171             :                                     "    return 42;"
   14172             :                                     "  } catch (e) {"
   14173             :                                     "    return e * 13;"
   14174             :                                     "  }"
   14175             :                                     "})();");
   14176          15 :   CHECK_EQ(91, script->Run(env.local())
   14177             :                    .ToLocalChecked()
   14178             :                    ->Int32Value(env.local())
   14179           5 :                    .FromJust());
   14180           5 : }
   14181             : 
   14182             : 
   14183       28343 : THREADED_TEST(RecursiveLocking) {
   14184           6 :   v8::Locker locker(CcTest::isolate());
   14185             :   {
   14186           6 :     v8::Locker locker2(CcTest::isolate());
   14187           6 :     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   14188           6 :   }
   14189           6 : }
   14190             : 
   14191             : 
   14192          12 : static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   14193          12 :   ApiTestFuzzer::Fuzz();
   14194          24 :   v8::Unlocker unlocker(CcTest::isolate());
   14195          12 : }
   14196             : 
   14197             : 
   14198       28343 : THREADED_TEST(LockUnlockLock) {
   14199             :   {
   14200           6 :     v8::Locker locker(CcTest::isolate());
   14201          12 :     v8::HandleScope scope(CcTest::isolate());
   14202          12 :     LocalContext env;
   14203             :     Local<v8::FunctionTemplate> fun_templ =
   14204           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   14205          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   14206          30 :     CHECK(env->Global()
   14207             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   14208             :               .FromJust());
   14209             :     Local<Script> script = v8_compile("(function () {"
   14210             :                                       "  unlock_for_a_moment();"
   14211             :                                       "  return 42;"
   14212             :                                       "})();");
   14213          18 :     CHECK_EQ(42, script->Run(env.local())
   14214             :                      .ToLocalChecked()
   14215             :                      ->Int32Value(env.local())
   14216           6 :                      .FromJust());
   14217             :   }
   14218             :   {
   14219           6 :     v8::Locker locker(CcTest::isolate());
   14220          12 :     v8::HandleScope scope(CcTest::isolate());
   14221          12 :     LocalContext env;
   14222             :     Local<v8::FunctionTemplate> fun_templ =
   14223           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   14224          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   14225          30 :     CHECK(env->Global()
   14226             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   14227             :               .FromJust());
   14228             :     Local<Script> script = v8_compile("(function () {"
   14229             :                                       "  unlock_for_a_moment();"
   14230             :                                       "  return 42;"
   14231             :                                       "})();");
   14232          18 :     CHECK_EQ(42, script->Run(env.local())
   14233             :                      .ToLocalChecked()
   14234             :                      ->Int32Value(env.local())
   14235           6 :                      .FromJust());
   14236             :   }
   14237           6 : }
   14238             : 
   14239             : 
   14240         130 : static int GetGlobalObjectsCount() {
   14241             :   int count = 0;
   14242         130 :   i::HeapIterator it(CcTest::heap());
   14243     1398494 :   for (i::HeapObject object = it.next(); !object.is_null();
   14244             :        object = it.next()) {
   14245      699117 :     if (object->IsJSGlobalObject()) {
   14246          30 :       i::JSGlobalObject g = i::JSGlobalObject::cast(object);
   14247             :       // Skip dummy global object.
   14248          30 :       if (g->global_dictionary()->NumberOfElements() != 0) {
   14249          30 :         count++;
   14250             :       }
   14251             :     }
   14252             :   }
   14253         130 :   return count;
   14254             : }
   14255             : 
   14256             : 
   14257         100 : static void CheckSurvivingGlobalObjectsCount(int expected) {
   14258             :   // We need to collect all garbage twice to be sure that everything
   14259             :   // has been collected.  This is because inline caches are cleared in
   14260             :   // the first garbage collection but some of the maps have already
   14261             :   // been marked at that point.  Therefore some of the maps are not
   14262             :   // collected until the second garbage collection.
   14263         100 :   CcTest::CollectAllGarbage();
   14264         100 :   CcTest::CollectAllGarbage();
   14265         100 :   int count = GetGlobalObjectsCount();
   14266         100 :   CHECK_EQ(expected, count);
   14267         100 : }
   14268             : 
   14269             : 
   14270       28342 : TEST(DontLeakGlobalObjects) {
   14271             :   // Regression test for issues 1139850 and 1174891.
   14272             : 
   14273           5 :   i::FLAG_expose_gc = true;
   14274           5 :   v8::V8::Initialize();
   14275             : 
   14276          30 :   for (int i = 0; i < 5; i++) {
   14277          25 :     { v8::HandleScope scope(CcTest::isolate());
   14278          25 :       LocalContext context;
   14279             :     }
   14280          25 :     CcTest::isolate()->ContextDisposedNotification();
   14281          25 :     CheckSurvivingGlobalObjectsCount(0);
   14282             : 
   14283          25 :     { v8::HandleScope scope(CcTest::isolate());
   14284          50 :       LocalContext context;
   14285          75 :       v8_compile("Date")->Run(context.local()).ToLocalChecked();
   14286             :     }
   14287          25 :     CcTest::isolate()->ContextDisposedNotification();
   14288          25 :     CheckSurvivingGlobalObjectsCount(0);
   14289             : 
   14290          25 :     { v8::HandleScope scope(CcTest::isolate());
   14291          50 :       LocalContext context;
   14292          75 :       v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
   14293             :     }
   14294          25 :     CcTest::isolate()->ContextDisposedNotification();
   14295          25 :     CheckSurvivingGlobalObjectsCount(0);
   14296             : 
   14297          25 :     { v8::HandleScope scope(CcTest::isolate());
   14298          25 :       const char* extension_list[] = { "v8/gc" };
   14299             :       v8::ExtensionConfiguration extensions(1, extension_list);
   14300          50 :       LocalContext context(&extensions);
   14301          75 :       v8_compile("gc();")->Run(context.local()).ToLocalChecked();
   14302             :     }
   14303          25 :     CcTest::isolate()->ContextDisposedNotification();
   14304          25 :     CheckSurvivingGlobalObjectsCount(0);
   14305             :   }
   14306           5 : }
   14307             : 
   14308             : 
   14309       28342 : TEST(CopyablePersistent) {
   14310           5 :   LocalContext context;
   14311           5 :   v8::Isolate* isolate = context->GetIsolate();
   14312          25 :   i::GlobalHandles* globals =
   14313             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   14314             :   int initial_handles = globals->global_handles_count();
   14315             :   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   14316             :       CopyableObject;
   14317             :   {
   14318             :     CopyableObject handle1;
   14319             :     {
   14320           5 :       v8::HandleScope scope(isolate);
   14321          10 :       handle1.Reset(isolate, v8::Object::New(isolate));
   14322             :     }
   14323           5 :     CHECK_EQ(initial_handles + 1, globals->global_handles_count());
   14324             :     CopyableObject  handle2;
   14325             :     handle2 = handle1;
   14326           5 :     CHECK(handle1 == handle2);
   14327           5 :     CHECK_EQ(initial_handles + 2, globals->global_handles_count());
   14328             :     CopyableObject handle3(handle2);
   14329           5 :     CHECK(handle1 == handle3);
   14330           5 :     CHECK_EQ(initial_handles + 3, globals->global_handles_count());
   14331             :   }
   14332             :   // Verify autodispose
   14333           5 :   CHECK_EQ(initial_handles, globals->global_handles_count());
   14334           5 : }
   14335             : 
   14336             : 
   14337           5 : static void WeakApiCallback(
   14338          10 :     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
   14339             :   data.GetParameter()->Reset();
   14340           5 :   delete data.GetParameter();
   14341           5 : }
   14342             : 
   14343             : 
   14344       28342 : TEST(WeakCallbackApi) {
   14345           5 :   LocalContext context;
   14346           5 :   v8::Isolate* isolate = context->GetIsolate();
   14347          10 :   i::GlobalHandles* globals =
   14348             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   14349             :   int initial_handles = globals->global_handles_count();
   14350             :   {
   14351           5 :     v8::HandleScope scope(isolate);
   14352           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   14353          25 :     CHECK(
   14354             :         obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
   14355             :             .FromJust());
   14356             :     v8::Persistent<v8::Object>* handle =
   14357           5 :         new v8::Persistent<v8::Object>(isolate, obj);
   14358             :     handle->SetWeak<v8::Persistent<v8::Object>>(
   14359           5 :         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
   14360             :   }
   14361           5 :   CcTest::PreciseCollectAllGarbage();
   14362             :   // Verify disposed.
   14363           5 :   CHECK_EQ(initial_handles, globals->global_handles_count());
   14364           5 : }
   14365             : 
   14366             : 
   14367       28337 : v8::Persistent<v8::Object> some_object;
   14368       28337 : v8::Persistent<v8::Object> bad_handle;
   14369             : 
   14370             : 
   14371           6 : void NewPersistentHandleCallback2(
   14372          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14373           6 :   v8::HandleScope scope(data.GetIsolate());
   14374           6 :   bad_handle.Reset(data.GetIsolate(), some_object);
   14375           6 : }
   14376             : 
   14377             : 
   14378           6 : void NewPersistentHandleCallback1(
   14379          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14380             :   data.GetParameter()->Reset();
   14381             :   data.SetSecondPassCallback(NewPersistentHandleCallback2);
   14382           6 : }
   14383             : 
   14384             : 
   14385       28343 : THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   14386           6 :   LocalContext context;
   14387           6 :   v8::Isolate* isolate = context->GetIsolate();
   14388             : 
   14389             :   v8::Persistent<v8::Object> handle1, handle2;
   14390             :   {
   14391           6 :     v8::HandleScope scope(isolate);
   14392          12 :     some_object.Reset(isolate, v8::Object::New(isolate));
   14393          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   14394          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   14395             :   }
   14396             :   // Note: order is implementation dependent alas: currently
   14397             :   // global handle nodes are processed by PostGarbageCollectionProcessing
   14398             :   // in reverse allocation order, so if second allocated handle is deleted,
   14399             :   // weak callback of the first handle would be able to 'reallocate' it.
   14400             :   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
   14401             :                   v8::WeakCallbackType::kParameter);
   14402             :   handle2.Reset();
   14403           6 :   CcTest::CollectAllGarbage();
   14404           6 : }
   14405             : 
   14406             : 
   14407       28337 : v8::Persistent<v8::Object> to_be_disposed;
   14408             : 
   14409             : 
   14410           6 : void DisposeAndForceGcCallback2(
   14411             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14412             :   to_be_disposed.Reset();
   14413           6 :   CcTest::CollectAllGarbage();
   14414           6 : }
   14415             : 
   14416             : 
   14417           6 : void DisposeAndForceGcCallback1(
   14418          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14419             :   data.GetParameter()->Reset();
   14420             :   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
   14421           6 : }
   14422             : 
   14423             : 
   14424       28343 : THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   14425           6 :   LocalContext context;
   14426           6 :   v8::Isolate* isolate = context->GetIsolate();
   14427             : 
   14428             :   v8::Persistent<v8::Object> handle1, handle2;
   14429             :   {
   14430           6 :     v8::HandleScope scope(isolate);
   14431          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   14432          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   14433             :   }
   14434             :   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
   14435             :                   v8::WeakCallbackType::kParameter);
   14436             :   to_be_disposed.Reset(isolate, handle2);
   14437           6 :   CcTest::CollectAllGarbage();
   14438           6 : }
   14439             : 
   14440           6 : void DisposingCallback(
   14441           6 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14442             :   data.GetParameter()->Reset();
   14443           6 : }
   14444             : 
   14445           6 : void HandleCreatingCallback2(
   14446          18 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14447           6 :   v8::HandleScope scope(data.GetIsolate());
   14448          12 :   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
   14449           6 : }
   14450             : 
   14451             : 
   14452           6 : void HandleCreatingCallback1(
   14453          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   14454             :   data.GetParameter()->Reset();
   14455             :   data.SetSecondPassCallback(HandleCreatingCallback2);
   14456           6 : }
   14457             : 
   14458             : 
   14459       28343 : THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   14460           6 :   v8::Locker locker(CcTest::isolate());
   14461          12 :   LocalContext context;
   14462           6 :   v8::Isolate* isolate = context->GetIsolate();
   14463             : 
   14464             :   v8::Persistent<v8::Object> handle1, handle2, handle3;
   14465             :   {
   14466           6 :     v8::HandleScope scope(isolate);
   14467          12 :     handle3.Reset(isolate, v8::Object::New(isolate));
   14468          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   14469          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   14470             :   }
   14471             :   handle2.SetWeak(&handle2, DisposingCallback,
   14472             :                   v8::WeakCallbackType::kParameter);
   14473             :   handle3.SetWeak(&handle3, HandleCreatingCallback1,
   14474             :                   v8::WeakCallbackType::kParameter);
   14475           6 :   CcTest::CollectAllGarbage();
   14476          12 :   EmptyMessageQueues(isolate);
   14477           6 : }
   14478             : 
   14479             : 
   14480       28343 : THREADED_TEST(CheckForCrossContextObjectLiterals) {
   14481           6 :   v8::V8::Initialize();
   14482             : 
   14483             :   const int nof = 2;
   14484             :   const char* sources[nof] = {
   14485             :     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   14486             :     "Object()"
   14487           6 :   };
   14488             : 
   14489          18 :   for (int i = 0; i < nof; i++) {
   14490          12 :     const char* source = sources[i];
   14491          12 :     { v8::HandleScope scope(CcTest::isolate());
   14492          24 :       LocalContext context;
   14493          12 :       CompileRun(source);
   14494             :     }
   14495          12 :     { v8::HandleScope scope(CcTest::isolate());
   14496          24 :       LocalContext context;
   14497          12 :       CompileRun(source);
   14498             :     }
   14499             :   }
   14500           6 : }
   14501             : 
   14502             : 
   14503           6 : static v8::Local<Value> NestedScope(v8::Local<Context> env) {
   14504           6 :   v8::EscapableHandleScope inner(env->GetIsolate());
   14505           6 :   env->Enter();
   14506           6 :   v8::Local<Value> three = v8_num(3);
   14507             :   v8::Local<Value> value = inner.Escape(three);
   14508           6 :   env->Exit();
   14509          12 :   return value;
   14510             : }
   14511             : 
   14512             : 
   14513       28343 : THREADED_TEST(NestedHandleScopeAndContexts) {
   14514           6 :   v8::Isolate* isolate = CcTest::isolate();
   14515           6 :   v8::HandleScope outer(isolate);
   14516           6 :   v8::Local<Context> env = Context::New(isolate);
   14517           6 :   env->Enter();
   14518           6 :   v8::Local<Value> value = NestedScope(env);
   14519           6 :   v8::Local<String> str(value->ToString(env).ToLocalChecked());
   14520           6 :   CHECK(!str.IsEmpty());
   14521           6 :   env->Exit();
   14522           6 : }
   14523             : 
   14524             : static v8::base::HashMap* code_map = nullptr;
   14525             : static v8::base::HashMap* jitcode_line_info = nullptr;
   14526             : static int saw_bar = 0;
   14527             : static int move_events = 0;
   14528             : 
   14529             : 
   14530        5381 : static bool FunctionNameIs(const char* expected,
   14531             :                            const v8::JitCodeEvent* event) {
   14532             :   // Log lines for functions are of the general form:
   14533             :   // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
   14534             :   // where the type is one of "*", "~" or "".
   14535             :   static const char* kPreamble;
   14536        5381 :   if (!i::FLAG_lazy) {
   14537           0 :     kPreamble = "Function:";
   14538             :   } else {
   14539        5381 :     kPreamble = "LazyCompile:";
   14540             :   }
   14541        5381 :   static size_t kPreambleLen = strlen(kPreamble);
   14542             : 
   14543       10707 :   if (event->name.len < kPreambleLen ||
   14544        5326 :       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   14545             :     return false;
   14546             :   }
   14547             : 
   14548         153 :   const char* tail = event->name.str + kPreambleLen;
   14549         153 :   size_t tail_len = event->name.len - kPreambleLen;
   14550         153 :   size_t expected_len = strlen(expected);
   14551         153 :   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   14552         148 :     --tail_len;
   14553         148 :     ++tail;
   14554             :   }
   14555             : 
   14556             :   // Check for tails like 'bar :1'.
   14557         285 :   if (tail_len > expected_len + 2 &&
   14558         264 :       tail[expected_len] == ' ' &&
   14559         264 :       tail[expected_len + 1] == ':' &&
   14560         264 :       tail[expected_len + 2] &&
   14561         132 :       !strncmp(tail, expected, expected_len)) {
   14562             :     return true;
   14563             :   }
   14564             : 
   14565          87 :   if (tail_len != expected_len)
   14566             :     return false;
   14567             : 
   14568          21 :   return strncmp(tail, expected, expected_len) == 0;
   14569             : }
   14570             : 
   14571             : 
   14572        7662 : static void event_handler(const v8::JitCodeEvent* event) {
   14573        7662 :   CHECK_NOT_NULL(event);
   14574        7662 :   CHECK_NOT_NULL(code_map);
   14575        7662 :   CHECK_NOT_NULL(jitcode_line_info);
   14576             : 
   14577             :   class DummyJitCodeLineInfo {
   14578             :   };
   14579             : 
   14580        7662 :   switch (event->type) {
   14581             :     case v8::JitCodeEvent::CODE_ADDED: {
   14582        5381 :       CHECK_NOT_NULL(event->code_start);
   14583        5381 :       CHECK_NE(0, static_cast<int>(event->code_len));
   14584        5381 :       CHECK_NOT_NULL(event->name.str);
   14585             :       v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
   14586        5381 :           event->code_start, i::ComputePointerHash(event->code_start));
   14587        5381 :       entry->value = reinterpret_cast<void*>(event->code_len);
   14588             : 
   14589        5381 :       if (FunctionNameIs("bar", event)) {
   14590          66 :         ++saw_bar;
   14591             :         }
   14592             :       }
   14593             :       break;
   14594             : 
   14595             :     case v8::JitCodeEvent::CODE_MOVED: {
   14596         171 :         uint32_t hash = i::ComputePointerHash(event->code_start);
   14597             :         // We would like to never see code move that we haven't seen before,
   14598             :         // but the code creation event does not happen until the line endings
   14599             :         // have been calculated (this is so that we can report the line in the
   14600             :         // script at which the function source is found, see
   14601             :         // Compiler::RecordFunctionCompilation) and the line endings
   14602             :         // calculations can cause a GC, which can move the newly created code
   14603             :         // before its existence can be logged.
   14604             :         v8::base::HashMap::Entry* entry =
   14605         171 :             code_map->Lookup(event->code_start, hash);
   14606         171 :         if (entry != nullptr) {
   14607         171 :           ++move_events;
   14608             : 
   14609         171 :           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   14610         171 :           code_map->Remove(event->code_start, hash);
   14611             : 
   14612             :           entry = code_map->LookupOrInsert(
   14613             :               event->new_code_start,
   14614         342 :               i::ComputePointerHash(event->new_code_start));
   14615         171 :           entry->value = reinterpret_cast<void*>(event->code_len);
   14616             :         }
   14617             :       }
   14618             :       break;
   14619             : 
   14620             :     case v8::JitCodeEvent::CODE_REMOVED:
   14621             :       // Object/code removal events are currently not dispatched from the GC.
   14622           0 :       UNREACHABLE();
   14623             : 
   14624             :     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14625             :     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14626             :     // record it in jitcode_line_info.
   14627             :     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14628         180 :         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14629             :         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14630         180 :         temp_event->user_data = line_info;
   14631             :         v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
   14632         360 :             line_info, i::ComputePointerHash(line_info));
   14633         180 :         entry->value = reinterpret_cast<void*>(line_info);
   14634             :       }
   14635         180 :       break;
   14636             :     // For these two events, we will check whether the event->user_data
   14637             :     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14638             :     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14639             :     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14640         180 :       CHECK_NOT_NULL(event->user_data);
   14641             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14642             :       v8::base::HashMap::Entry* entry =
   14643         180 :           jitcode_line_info->Lookup(event->user_data, hash);
   14644         180 :       CHECK_NOT_NULL(entry);
   14645         180 :       delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14646             :       }
   14647         180 :       break;
   14648             : 
   14649             :     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14650        1750 :       CHECK_NOT_NULL(event->user_data);
   14651             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14652             :       v8::base::HashMap::Entry* entry =
   14653        1750 :           jitcode_line_info->Lookup(event->user_data, hash);
   14654        1750 :       CHECK_NOT_NULL(entry);
   14655             :       }
   14656             :       break;
   14657             : 
   14658             :     default:
   14659             :       // Impossible event.
   14660           0 :       UNREACHABLE();
   14661             :   }
   14662        7662 : }
   14663             : 
   14664             : 
   14665       28342 : UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14666           5 :   i::FLAG_stress_compaction = true;
   14667           5 :   i::FLAG_incremental_marking = false;
   14668           5 :   if (i::FLAG_never_compact) return;
   14669             :   const char* script =
   14670             :       "function bar() {"
   14671             :       "  var sum = 0;"
   14672             :       "  for (i = 0; i < 10; ++i)"
   14673             :       "    sum = foo(i);"
   14674             :       "  return sum;"
   14675             :       "}"
   14676             :       "function foo(i) { return i; };"
   14677             :       "bar();";
   14678             : 
   14679             :   // Run this test in a new isolate to make sure we don't
   14680             :   // have remnants of state from other code.
   14681             :   v8::Isolate::CreateParams create_params;
   14682           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14683          55 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14684           5 :   isolate->Enter();
   14685             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14686           5 :   i::Heap* heap = i_isolate->heap();
   14687             : 
   14688             :   // Start with a clean slate.
   14689           5 :   heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14690             : 
   14691             :   {
   14692           5 :     v8::HandleScope scope(isolate);
   14693             :     v8::base::HashMap code;
   14694           5 :     code_map = &code;
   14695             : 
   14696             :     v8::base::HashMap lineinfo;
   14697           5 :     jitcode_line_info = &lineinfo;
   14698             : 
   14699           5 :     saw_bar = 0;
   14700           5 :     move_events = 0;
   14701             : 
   14702           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14703             : 
   14704             :     // Generate new code objects sparsely distributed across several
   14705             :     // different fragmented code-space pages.
   14706             :     const int kIterations = 10;
   14707          55 :     for (int i = 0; i < kIterations; ++i) {
   14708             :       LocalContext env(isolate);
   14709             :       i::AlwaysAllocateScope always_allocate(i_isolate);
   14710             :       CompileRun(script);
   14711             : 
   14712             :       // Keep a strong reference to the code object in the handle scope.
   14713             :       i::Handle<i::JSFunction> bar(i::Handle<i::JSFunction>::cast(
   14714             :           v8::Utils::OpenHandle(*env->Global()
   14715         200 :                                      ->Get(env.local(), v8_str("bar"))
   14716         100 :                                      .ToLocalChecked())));
   14717             :       i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   14718             :           v8::Utils::OpenHandle(*env->Global()
   14719         200 :                                      ->Get(env.local(), v8_str("foo"))
   14720         100 :                                      .ToLocalChecked())));
   14721             : 
   14722             :       i::PagedSpace* foo_owning_space = reinterpret_cast<i::PagedSpace*>(
   14723         100 :           i::Page::FromHeapObject(foo->abstract_code())->owner());
   14724             :       i::PagedSpace* bar_owning_space = reinterpret_cast<i::PagedSpace*>(
   14725         100 :           i::Page::FromHeapObject(bar->abstract_code())->owner());
   14726          50 :       CHECK_EQ(foo_owning_space, bar_owning_space);
   14727          50 :       i::heap::SimulateFullSpace(foo_owning_space);
   14728             : 
   14729             :       // Clear the compilation cache to get more wastage.
   14730          50 :       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14731          50 :     }
   14732             : 
   14733             :     // Force code movement.
   14734           5 :     heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14735             : 
   14736           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14737             : 
   14738           5 :     CHECK_LE(kIterations, saw_bar);
   14739           5 :     CHECK_LT(0, move_events);
   14740             : 
   14741           5 :     code_map = nullptr;
   14742          10 :     jitcode_line_info = nullptr;
   14743             :   }
   14744             : 
   14745           5 :   isolate->Exit();
   14746           5 :   isolate->Dispose();
   14747             : 
   14748             :   // Do this in a new isolate.
   14749           5 :   isolate = v8::Isolate::New(create_params);
   14750           5 :   isolate->Enter();
   14751             : 
   14752             :   // Verify that we get callbacks for existing code objects when we
   14753             :   // request enumeration of existing code.
   14754             :   {
   14755           5 :     v8::HandleScope scope(isolate);
   14756           5 :     LocalContext env(isolate);
   14757             :     CompileRun(script);
   14758             : 
   14759             :     // Now get code through initial iteration.
   14760             :     v8::base::HashMap code;
   14761           5 :     code_map = &code;
   14762             : 
   14763             :     v8::base::HashMap lineinfo;
   14764           5 :     jitcode_line_info = &lineinfo;
   14765             : 
   14766             :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14767           5 :                                     event_handler);
   14768           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14769             : 
   14770           5 :     jitcode_line_info = nullptr;
   14771             :     // We expect that we got some events. Note that if we could get code removal
   14772             :     // notifications, we could compare two collections, one created by listening
   14773             :     // from the time of creation of an isolate, and the other by subscribing
   14774             :     // with EnumExisting.
   14775           5 :     CHECK_LT(0u, code.occupancy());
   14776             : 
   14777          10 :     code_map = nullptr;
   14778             :   }
   14779             : 
   14780           5 :   isolate->Exit();
   14781           5 :   isolate->Dispose();
   14782             : }
   14783             : 
   14784       28342 : TEST(ExternalAllocatedMemory) {
   14785           5 :   v8::Isolate* isolate = CcTest::isolate();
   14786           5 :   v8::HandleScope outer(isolate);
   14787           5 :   v8::Local<Context> env(Context::New(isolate));
   14788           5 :   CHECK(!env.IsEmpty());
   14789             :   const int64_t kSize = 1024*1024;
   14790             :   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14791           5 :   CHECK_EQ(baseline + kSize,
   14792             :            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14793           5 :   CHECK_EQ(baseline,
   14794             :            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14795             :   const int64_t kTriggerGCSize =
   14796           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14797           5 :   CHECK_EQ(baseline + kTriggerGCSize,
   14798             :            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   14799          10 :   CHECK_EQ(baseline,
   14800           5 :            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
   14801           5 : }
   14802             : 
   14803             : 
   14804       28342 : TEST(Regress51719) {
   14805           5 :   i::FLAG_incremental_marking = false;
   14806           5 :   CcTest::InitializeVM();
   14807             : 
   14808             :   const int64_t kTriggerGCSize =
   14809           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14810           5 :   v8::Isolate* isolate = CcTest::isolate();
   14811             :   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
   14812           5 : }
   14813             : 
   14814             : // Regression test for issue 54, object templates with embedder fields
   14815             : // but no accessors or interceptors did not get their embedder field
   14816             : // count set on instances.
   14817       28343 : THREADED_TEST(Regress54) {
   14818           6 :   LocalContext context;
   14819           6 :   v8::Isolate* isolate = context->GetIsolate();
   14820          12 :   v8::HandleScope outer(isolate);
   14821          12 :   static v8::Persistent<v8::ObjectTemplate> templ;
   14822           6 :   if (templ.IsEmpty()) {
   14823           6 :     v8::EscapableHandleScope inner(isolate);
   14824           6 :     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14825           6 :     local->SetInternalFieldCount(1);
   14826             :     templ.Reset(isolate, inner.Escape(local));
   14827             :   }
   14828             :   v8::Local<v8::Object> result =
   14829             :       v8::Local<v8::ObjectTemplate>::New(isolate, templ)
   14830           6 :           ->NewInstance(context.local())
   14831           6 :           .ToLocalChecked();
   14832          12 :   CHECK_EQ(1, result->InternalFieldCount());
   14833           6 : }
   14834             : 
   14835             : 
   14836             : // If part of the threaded tests, this test makes ThreadingTest fail
   14837             : // on mac.
   14838       28342 : TEST(CatchStackOverflow) {
   14839           5 :   LocalContext context;
   14840          10 :   v8::HandleScope scope(context->GetIsolate());
   14841          10 :   v8::TryCatch try_catch(context->GetIsolate());
   14842             :   v8::Local<v8::Value> result = CompileRun(
   14843             :       "function f() {"
   14844             :       "  return f();"
   14845             :       "}"
   14846             :       ""
   14847             :       "f();");
   14848          10 :   CHECK(result.IsEmpty());
   14849           5 : }
   14850             : 
   14851             : 
   14852          18 : static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
   14853             :                                     const char* resource_name,
   14854             :                                     int line_offset) {
   14855          18 :   v8::HandleScope scope(CcTest::isolate());
   14856          36 :   v8::TryCatch try_catch(CcTest::isolate());
   14857          18 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   14858          36 :   CHECK(script->Run(context).IsEmpty());
   14859          18 :   CHECK(try_catch.HasCaught());
   14860          18 :   v8::Local<v8::Message> message = try_catch.Message();
   14861          18 :   CHECK(!message.IsEmpty());
   14862          36 :   CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
   14863          18 :   CHECK_EQ(91, message->GetStartPosition());
   14864          18 :   CHECK_EQ(92, message->GetEndPosition());
   14865          36 :   CHECK_EQ(2, message->GetStartColumn(context).FromJust());
   14866          36 :   CHECK_EQ(3, message->GetEndColumn(context).FromJust());
   14867             :   v8::String::Utf8Value line(CcTest::isolate(),
   14868          54 :                              message->GetSourceLine(context).ToLocalChecked());
   14869          18 :   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
   14870             :   v8::String::Utf8Value name(CcTest::isolate(),
   14871          36 :                              message->GetScriptOrigin().ResourceName());
   14872          36 :   CHECK_EQ(0, strcmp(resource_name, *name));
   14873          18 : }
   14874             : 
   14875             : 
   14876       28343 : THREADED_TEST(TryCatchSourceInfo) {
   14877           6 :   LocalContext context;
   14878          12 :   v8::HandleScope scope(context->GetIsolate());
   14879             :   v8::Local<v8::String> source = v8_str(
   14880             :       "function Foo() {\n"
   14881             :       "  return Bar();\n"
   14882             :       "}\n"
   14883             :       "\n"
   14884             :       "function Bar() {\n"
   14885             :       "  return Baz();\n"
   14886             :       "}\n"
   14887             :       "\n"
   14888             :       "function Baz() {\n"
   14889             :       "  throw 'nirk';\n"
   14890             :       "}\n"
   14891             :       "\n"
   14892           6 :       "Foo();\n");
   14893             : 
   14894             :   const char* resource_name;
   14895             :   v8::Local<v8::Script> script;
   14896             :   resource_name = "test.js";
   14897           6 :   script = CompileWithOrigin(source, resource_name);
   14898           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14899             : 
   14900             :   resource_name = "test1.js";
   14901           6 :   v8::ScriptOrigin origin1(v8_str(resource_name));
   14902             :   script =
   14903          12 :       v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
   14904           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14905             : 
   14906             :   resource_name = "test2.js";
   14907             :   v8::ScriptOrigin origin2(v8_str(resource_name),
   14908           6 :                            v8::Integer::New(context->GetIsolate(), 7));
   14909             :   script =
   14910          12 :       v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
   14911          12 :   CheckTryCatchSourceInfo(script, resource_name, 7);
   14912           6 : }
   14913             : 
   14914             : 
   14915       28343 : THREADED_TEST(TryCatchSourceInfoForEOSError) {
   14916           6 :   LocalContext context;
   14917          12 :   v8::HandleScope scope(context->GetIsolate());
   14918          12 :   v8::TryCatch try_catch(context->GetIsolate());
   14919          12 :   CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
   14920           6 :   CHECK(try_catch.HasCaught());
   14921           6 :   v8::Local<v8::Message> message = try_catch.Message();
   14922          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   14923          18 :   CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
   14924           6 : }
   14925             : 
   14926             : 
   14927       28343 : THREADED_TEST(CompilationCache) {
   14928           6 :   LocalContext context;
   14929          12 :   v8::HandleScope scope(context->GetIsolate());
   14930           6 :   v8::Local<v8::String> source0 = v8_str("1234");
   14931           6 :   v8::Local<v8::String> source1 = v8_str("1234");
   14932             :   v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
   14933             :   v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
   14934           6 :   v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
   14935           6 :                                       .ToLocalChecked();  // different origin
   14936          18 :   CHECK_EQ(1234, script0->Run(context.local())
   14937             :                      .ToLocalChecked()
   14938             :                      ->Int32Value(context.local())
   14939             :                      .FromJust());
   14940          18 :   CHECK_EQ(1234, script1->Run(context.local())
   14941             :                      .ToLocalChecked()
   14942             :                      ->Int32Value(context.local())
   14943             :                      .FromJust());
   14944          18 :   CHECK_EQ(1234, script2->Run(context.local())
   14945             :                      .ToLocalChecked()
   14946             :                      ->Int32Value(context.local())
   14947           6 :                      .FromJust());
   14948           6 : }
   14949             : 
   14950             : 
   14951           0 : static void FunctionNameCallback(
   14952           0 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14953           0 :   ApiTestFuzzer::Fuzz();
   14954           0 :   args.GetReturnValue().Set(v8_num(42));
   14955           0 : }
   14956             : 
   14957             : 
   14958       28343 : THREADED_TEST(CallbackFunctionName) {
   14959           6 :   LocalContext context;
   14960           6 :   v8::Isolate* isolate = context->GetIsolate();
   14961          12 :   v8::HandleScope scope(isolate);
   14962           6 :   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14963             :   t->Set(v8_str("asdf"),
   14964          18 :          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   14965          36 :   CHECK(context->Global()
   14966             :             ->Set(context.local(), v8_str("obj"),
   14967             :                   t->NewInstance(context.local()).ToLocalChecked())
   14968             :             .FromJust());
   14969             :   v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
   14970           6 :   CHECK(value->IsString());
   14971          12 :   v8::String::Utf8Value name(isolate, value);
   14972          12 :   CHECK_EQ(0, strcmp("asdf", *name));
   14973           6 : }
   14974             : 
   14975             : 
   14976       28343 : THREADED_TEST(DateAccess) {
   14977           6 :   LocalContext context;
   14978          12 :   v8::HandleScope scope(context->GetIsolate());
   14979             :   v8::Local<v8::Value> date =
   14980           6 :       v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
   14981           6 :   CHECK(date->IsDate());
   14982          12 :   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   14983           6 : }
   14984             : 
   14985          48 : void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   14986             :                      unsigned index, const char* name) {
   14987          48 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14988             :   v8::Local<v8::Value> value =
   14989          96 :       properties->Get(context, v8::Integer::New(isolate, index))
   14990          48 :           .ToLocalChecked();
   14991          48 :   CHECK(value->IsSymbol());
   14992             :   v8::String::Utf8Value symbol_name(isolate,
   14993          48 :                                     Local<Symbol>::Cast(value)->Name());
   14994          48 :   if (strcmp(name, *symbol_name) != 0) {
   14995             :     FATAL("properties[%u] was Symbol('%s') instead of Symbol('%s').", index,
   14996           0 :           name, *symbol_name);
   14997          48 :   }
   14998          48 : }
   14999             : 
   15000         150 : void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   15001             :                       unsigned length, const char* names[]) {
   15002         150 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15003         150 :   CHECK_EQ(length, properties->Length());
   15004         924 :   for (unsigned i = 0; i < length; i++) {
   15005             :     v8::Local<v8::Value> value =
   15006        2772 :         properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
   15007         924 :     if (names[i] == nullptr) {
   15008             :       DCHECK(value->IsSymbol());
   15009             :     } else {
   15010         876 :       v8::String::Utf8Value elm(isolate, value);
   15011         876 :       if (strcmp(names[i], *elm) != 0) {
   15012           0 :         FATAL("properties[%u] was '%s' instead of '%s'.", i, *elm, names[i]);
   15013         876 :       }
   15014             :     }
   15015             :   }
   15016         150 : }
   15017             : 
   15018          42 : void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   15019             :                      unsigned length, const char* names[]) {
   15020          42 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15021             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   15022          84 :   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
   15023          42 :   CheckStringArray(isolate, props, length, names);
   15024          42 : }
   15025             : 
   15026             : 
   15027          24 : void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   15028             :                         unsigned elmc, const char* elmv[]) {
   15029          24 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   15030             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   15031             :   v8::Local<v8::Array> props =
   15032          24 :       obj->GetOwnPropertyNames(context).ToLocalChecked();
   15033          24 :   CHECK_EQ(elmc, props->Length());
   15034          42 :   for (unsigned i = 0; i < elmc; i++) {
   15035             :     v8::String::Utf8Value elm(
   15036             :         isolate,
   15037         126 :         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   15038          42 :     CHECK_EQ(0, strcmp(elmv[i], *elm));
   15039          42 :   }
   15040          24 : }
   15041             : 
   15042             : 
   15043       28343 : THREADED_TEST(PropertyEnumeration) {
   15044           6 :   LocalContext context;
   15045           6 :   v8::Isolate* isolate = context->GetIsolate();
   15046          12 :   v8::HandleScope scope(isolate);
   15047             :   v8::Local<v8::Value> obj = CompileRun(
   15048             :       "var result = [];"
   15049             :       "result[0] = {};"
   15050             :       "result[1] = {a: 1, b: 2};"
   15051             :       "result[2] = [1, 2, 3];"
   15052             :       "var proto = {x: 1, y: 2, z: 3};"
   15053             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   15054             :       "result[3] = x;"
   15055             :       "result[4] = {21350:1};"
   15056             :       "x = Object.create(null);"
   15057             :       "x.a = 1; x[12345678] = 1;"
   15058             :       "result[5] = x;"
   15059             :       "result;");
   15060             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   15061           6 :   CHECK_EQ(6u, elms->Length());
   15062             :   int elmc0 = 0;
   15063             :   const char** elmv0 = nullptr;
   15064             :   CheckProperties(
   15065             :       isolate,
   15066          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15067          12 :       elmc0, elmv0);
   15068             :   CheckOwnProperties(
   15069             :       isolate,
   15070          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15071          12 :       elmc0, elmv0);
   15072             :   int elmc1 = 2;
   15073           6 :   const char* elmv1[] = {"a", "b"};
   15074             :   CheckProperties(
   15075             :       isolate,
   15076          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   15077          12 :       elmc1, elmv1);
   15078             :   CheckOwnProperties(
   15079             :       isolate,
   15080          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   15081          12 :       elmc1, elmv1);
   15082             :   int elmc2 = 3;
   15083           6 :   const char* elmv2[] = {"0", "1", "2"};
   15084             :   CheckProperties(
   15085             :       isolate,
   15086          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   15087          12 :       elmc2, elmv2);
   15088             :   CheckOwnProperties(
   15089             :       isolate,
   15090          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   15091          12 :       elmc2, elmv2);
   15092             :   int elmc3 = 4;
   15093           6 :   const char* elmv3[] = {"w", "z", "x", "y"};
   15094             :   CheckProperties(
   15095             :       isolate,
   15096          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   15097          12 :       elmc3, elmv3);
   15098             :   int elmc4 = 2;
   15099           6 :   const char* elmv4[] = {"w", "z"};
   15100             :   CheckOwnProperties(
   15101             :       isolate,
   15102          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   15103          12 :       elmc4, elmv4);
   15104             :   // Dictionary elements.
   15105             :   int elmc5 = 1;
   15106           6 :   const char* elmv5[] = {"21350"};
   15107             :   CheckProperties(
   15108             :       isolate,
   15109          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 4)).ToLocalChecked(),
   15110          12 :       elmc5, elmv5);
   15111             :   // Dictionary properties.
   15112             :   int elmc6 = 2;
   15113           6 :   const char* elmv6[] = {"12345678", "a"};
   15114             :   CheckProperties(
   15115             :       isolate,
   15116          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 5)).ToLocalChecked(),
   15117          18 :       elmc6, elmv6);
   15118           6 : }
   15119             : 
   15120             : 
   15121       28343 : THREADED_TEST(PropertyEnumeration2) {
   15122           6 :   LocalContext context;
   15123           6 :   v8::Isolate* isolate = context->GetIsolate();
   15124          12 :   v8::HandleScope scope(isolate);
   15125             :   v8::Local<v8::Value> obj = CompileRun(
   15126             :       "var result = [];"
   15127             :       "result[0] = {};"
   15128             :       "result[1] = {a: 1, b: 2};"
   15129             :       "result[2] = [1, 2, 3];"
   15130             :       "var proto = {x: 1, y: 2, z: 3};"
   15131             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   15132             :       "result[3] = x;"
   15133             :       "result;");
   15134             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   15135           6 :   CHECK_EQ(4u, elms->Length());
   15136             :   int elmc0 = 0;
   15137             :   const char** elmv0 = nullptr;
   15138             :   CheckProperties(
   15139             :       isolate,
   15140          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   15141          12 :       elmc0, elmv0);
   15142             : 
   15143             :   v8::Local<v8::Value> val =
   15144          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
   15145             :   v8::Local<v8::Array> props =
   15146           6 :       val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
   15147           6 :   CHECK_EQ(0u, props->Length());
   15148           0 :   for (uint32_t i = 0; i < props->Length(); i++) {
   15149             :     printf("p[%u]\n", i);
   15150           6 :   }
   15151           6 : }
   15152             : 
   15153       28343 : THREADED_TEST(GetPropertyNames) {
   15154           6 :   LocalContext context;
   15155           6 :   v8::Isolate* isolate = context->GetIsolate();
   15156          12 :   v8::HandleScope scope(isolate);
   15157             :   v8::Local<v8::Value> result = CompileRun(
   15158             :       "var result = {0: 0, 1: 1, a: 2, b: 3};"
   15159             :       "result[2**32] = '4294967296';"
   15160             :       "result[2**32-1] = '4294967295';"
   15161             :       "result[2**32-2] = '4294967294';"
   15162             :       "result[Symbol('symbol')] = true;"
   15163             :       "result.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
   15164             :       "result;");
   15165             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   15166             :   v8::PropertyFilter default_filter =
   15167             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   15168             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   15169             : 
   15170             :   v8::Local<v8::Array> properties =
   15171          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   15172             :   const char* expected_properties1[] = {"0", "1",          "4294967294", "a",
   15173             :                                         "b", "4294967296", "4294967295", "2",
   15174           6 :                                         "3", "c",          "d"};
   15175           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   15176             : 
   15177             :   properties =
   15178             :       object
   15179             :           ->GetPropertyNames(context.local(),
   15180             :                              v8::KeyCollectionMode::kIncludePrototypes,
   15181           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   15182          12 :           .ToLocalChecked();
   15183           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   15184             : 
   15185             :   properties = object
   15186             :                    ->GetPropertyNames(context.local(),
   15187             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   15188             :                                       include_symbols_filter,
   15189           6 :                                       v8::IndexFilter::kIncludeIndices)
   15190          12 :                    .ToLocalChecked();
   15191             :   const char* expected_properties1_1[] = {
   15192             :       "0",          "1",     "4294967294", "a", "b", "4294967296",
   15193           6 :       "4294967295", nullptr, "2",          "3", "c", "d"};
   15194           6 :   CheckStringArray(isolate, properties, 12, expected_properties1_1);
   15195           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   15196             : 
   15197             :   properties =
   15198             :       object
   15199             :           ->GetPropertyNames(context.local(),
   15200             :                              v8::KeyCollectionMode::kIncludePrototypes,
   15201           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   15202          12 :           .ToLocalChecked();
   15203             :   const char* expected_properties2[] = {"a",          "b", "4294967296",
   15204           6 :                                         "4294967295", "c", "d"};
   15205           6 :   CheckStringArray(isolate, properties, 6, expected_properties2);
   15206             : 
   15207             :   properties = object
   15208             :                    ->GetPropertyNames(context.local(),
   15209             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   15210             :                                       include_symbols_filter,
   15211           6 :                                       v8::IndexFilter::kSkipIndices)
   15212          12 :                    .ToLocalChecked();
   15213             :   const char* expected_properties2_1[] = {
   15214           6 :       "a", "b", "4294967296", "4294967295", nullptr, "c", "d"};
   15215           6 :   CheckStringArray(isolate, properties, 7, expected_properties2_1);
   15216           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15217             : 
   15218             :   properties =
   15219             :       object
   15220             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15221           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   15222          12 :           .ToLocalChecked();
   15223             :   const char* expected_properties3[] = {
   15224             :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295",
   15225           6 :   };
   15226           6 :   CheckStringArray(isolate, properties, 7, expected_properties3);
   15227             : 
   15228             :   properties = object
   15229             :                    ->GetPropertyNames(
   15230             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15231           6 :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   15232          12 :                    .ToLocalChecked();
   15233             :   const char* expected_properties3_1[] = {
   15234           6 :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295", nullptr};
   15235           6 :   CheckStringArray(isolate, properties, 8, expected_properties3_1);
   15236           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   15237             : 
   15238             :   properties =
   15239             :       object
   15240             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15241           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   15242          12 :           .ToLocalChecked();
   15243           6 :   const char* expected_properties4[] = {"a", "b", "4294967296", "4294967295"};
   15244           6 :   CheckStringArray(isolate, properties, 4, expected_properties4);
   15245             : 
   15246             :   properties = object
   15247             :                    ->GetPropertyNames(
   15248             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15249           6 :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   15250          12 :                    .ToLocalChecked();
   15251             :   const char* expected_properties4_1[] = {"a", "b", "4294967296", "4294967295",
   15252           6 :                                           nullptr};
   15253           6 :   CheckStringArray(isolate, properties, 5, expected_properties4_1);
   15254          12 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15255           6 : }
   15256             : 
   15257       28343 : THREADED_TEST(ProxyGetPropertyNames) {
   15258           6 :   LocalContext context;
   15259           6 :   v8::Isolate* isolate = context->GetIsolate();
   15260          12 :   v8::HandleScope scope(isolate);
   15261             :   v8::Local<v8::Value> result = CompileRun(
   15262             :       "var target = {0: 0, 1: 1, a: 2, b: 3};"
   15263             :       "target[2**32] = '4294967296';"
   15264             :       "target[2**32-1] = '4294967295';"
   15265             :       "target[2**32-2] = '4294967294';"
   15266             :       "target[Symbol('symbol')] = true;"
   15267             :       "target.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
   15268             :       "var result = new Proxy(target, {});"
   15269             :       "result;");
   15270             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   15271             :   v8::PropertyFilter default_filter =
   15272             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   15273             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   15274             : 
   15275             :   v8::Local<v8::Array> properties =
   15276          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   15277             :   const char* expected_properties1[] = {"0", "1",          "4294967294", "a",
   15278             :                                         "b", "4294967296", "4294967295", "2",
   15279           6 :                                         "3", "c",          "d"};
   15280           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   15281             : 
   15282             :   properties =
   15283             :       object
   15284             :           ->GetPropertyNames(context.local(),
   15285             :                              v8::KeyCollectionMode::kIncludePrototypes,
   15286           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   15287          12 :           .ToLocalChecked();
   15288           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   15289             : 
   15290             :   properties = object
   15291             :                    ->GetPropertyNames(context.local(),
   15292             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   15293             :                                       include_symbols_filter,
   15294           6 :                                       v8::IndexFilter::kIncludeIndices)
   15295          12 :                    .ToLocalChecked();
   15296             :   const char* expected_properties1_1[] = {
   15297             :       "0",          "1",     "4294967294", "a", "b", "4294967296",
   15298           6 :       "4294967295", nullptr, "2",          "3", "c", "d"};
   15299           6 :   CheckStringArray(isolate, properties, 12, expected_properties1_1);
   15300           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   15301             : 
   15302             :   properties =
   15303             :       object
   15304             :           ->GetPropertyNames(context.local(),
   15305             :                              v8::KeyCollectionMode::kIncludePrototypes,
   15306           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   15307          12 :           .ToLocalChecked();
   15308             :   const char* expected_properties2[] = {"a",          "b", "4294967296",
   15309           6 :                                         "4294967295", "c", "d"};
   15310           6 :   CheckStringArray(isolate, properties, 6, expected_properties2);
   15311             : 
   15312             :   properties = object
   15313             :                    ->GetPropertyNames(context.local(),
   15314             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   15315             :                                       include_symbols_filter,
   15316           6 :                                       v8::IndexFilter::kSkipIndices)
   15317          12 :                    .ToLocalChecked();
   15318             :   const char* expected_properties2_1[] = {
   15319           6 :       "a", "b", "4294967296", "4294967295", nullptr, "c", "d"};
   15320           6 :   CheckStringArray(isolate, properties, 7, expected_properties2_1);
   15321           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15322             : 
   15323             :   properties =
   15324             :       object
   15325             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15326           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   15327          12 :           .ToLocalChecked();
   15328             :   const char* expected_properties3[] = {"0", "1",          "4294967294", "a",
   15329           6 :                                         "b", "4294967296", "4294967295"};
   15330           6 :   CheckStringArray(isolate, properties, 7, expected_properties3);
   15331             : 
   15332             :   properties = object
   15333             :                    ->GetPropertyNames(
   15334             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15335           6 :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   15336          12 :                    .ToLocalChecked();
   15337             :   const char* expected_properties3_1[] = {
   15338           6 :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295", nullptr};
   15339           6 :   CheckStringArray(isolate, properties, 8, expected_properties3_1);
   15340           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   15341             : 
   15342             :   properties =
   15343             :       object
   15344             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   15345           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   15346          12 :           .ToLocalChecked();
   15347           6 :   const char* expected_properties4[] = {"a", "b", "4294967296", "4294967295"};
   15348           6 :   CheckStringArray(isolate, properties, 4, expected_properties4);
   15349             : 
   15350             :   properties = object
   15351             :                    ->GetPropertyNames(
   15352             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   15353           6 :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   15354          12 :                    .ToLocalChecked();
   15355             :   const char* expected_properties4_1[] = {"a", "b", "4294967296", "4294967295",
   15356           6 :                                           nullptr};
   15357           6 :   CheckStringArray(isolate, properties, 5, expected_properties4_1);
   15358          12 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   15359           6 : }
   15360             : 
   15361       28343 : THREADED_TEST(AccessChecksReenabledCorrectly) {
   15362           6 :   LocalContext context;
   15363           6 :   v8::Isolate* isolate = context->GetIsolate();
   15364          12 :   v8::HandleScope scope(isolate);
   15365           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   15366           6 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15367          18 :   templ->Set(v8_str("a"), v8_str("a"));
   15368             :   // Add more than 8 (see kMaxFastProperties) properties
   15369             :   // so that the constructor will force copying map.
   15370             :   // Cannot sprintf, gcc complains unsafety.
   15371             :   char buf[4];
   15372          66 :   for (char i = '0'; i <= '9' ; i++) {
   15373          60 :     buf[0] = i;
   15374         660 :     for (char j = '0'; j <= '9'; j++) {
   15375         600 :       buf[1] = j;
   15376        6600 :       for (char k = '0'; k <= '9'; k++) {
   15377        6000 :         buf[2] = k;
   15378        6000 :         buf[3] = 0;
   15379       18000 :         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   15380             :       }
   15381             :     }
   15382             :   }
   15383             : 
   15384             :   Local<v8::Object> instance_1 =
   15385           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   15386          30 :   CHECK(context->Global()
   15387             :             ->Set(context.local(), v8_str("obj_1"), instance_1)
   15388             :             .FromJust());
   15389             : 
   15390             :   Local<Value> value_1 = CompileRun("obj_1.a");
   15391           6 :   CHECK(value_1.IsEmpty());
   15392             : 
   15393             :   Local<v8::Object> instance_2 =
   15394           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   15395          30 :   CHECK(context->Global()
   15396             :             ->Set(context.local(), v8_str("obj_2"), instance_2)
   15397             :             .FromJust());
   15398             : 
   15399             :   Local<Value> value_2 = CompileRun("obj_2.a");
   15400          12 :   CHECK(value_2.IsEmpty());
   15401           6 : }
   15402             : 
   15403             : 
   15404             : // This tests that we do not allow dictionary load/call inline caches
   15405             : // to use functions that have not yet been compiled.  The potential
   15406             : // problem of loading a function that has not yet been compiled can
   15407             : // arise because we share code between contexts via the compilation
   15408             : // cache.
   15409       28343 : THREADED_TEST(DictionaryICLoadedFunction) {
   15410           6 :   v8::HandleScope scope(CcTest::isolate());
   15411             :   // Test LoadIC.
   15412          18 :   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++) new RegExp('');");
   15419          12 :   }
   15420             :   // Test CallIC.
   15421          12 :   for (int i = 0; i < 2; i++) {
   15422          12 :     LocalContext context;
   15423          72 :     CHECK(context->Global()
   15424             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   15425             :               .FromJust());
   15426          60 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   15427             :     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   15428          18 :   }
   15429           6 : }
   15430             : 
   15431             : 
   15432             : // Test that cross-context new calls use the context of the callee to
   15433             : // create the new JavaScript object.
   15434       28343 : THREADED_TEST(CrossContextNew) {
   15435           6 :   v8::Isolate* isolate = CcTest::isolate();
   15436           6 :   v8::HandleScope scope(isolate);
   15437           6 :   v8::Local<Context> context0 = Context::New(isolate);
   15438           6 :   v8::Local<Context> context1 = Context::New(isolate);
   15439             : 
   15440             :   // Allow cross-domain access.
   15441           6 :   Local<String> token = v8_str("<security token>");
   15442           6 :   context0->SetSecurityToken(token);
   15443           6 :   context1->SetSecurityToken(token);
   15444             : 
   15445             :   // Set an 'x' property on the Object prototype and define a
   15446             :   // constructor function in context0.
   15447           6 :   context0->Enter();
   15448             :   CompileRun("Object.prototype.x = 42; function C() {};");
   15449           6 :   context0->Exit();
   15450             : 
   15451             :   // Call the constructor function from context0 and check that the
   15452             :   // result has the 'x' property.
   15453           6 :   context1->Enter();
   15454          30 :   CHECK(context1->Global()
   15455             :             ->Set(context1, v8_str("other"), context0->Global())
   15456             :             .FromJust());
   15457             :   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   15458           6 :   CHECK(value->IsInt32());
   15459          12 :   CHECK_EQ(42, value->Int32Value(context1).FromJust());
   15460           6 :   context1->Exit();
   15461           6 : }
   15462             : 
   15463             : 
   15464             : // Verify that we can clone an object
   15465       28342 : TEST(ObjectClone) {
   15466           5 :   LocalContext env;
   15467           5 :   v8::Isolate* isolate = env->GetIsolate();
   15468          10 :   v8::HandleScope scope(isolate);
   15469             : 
   15470             :   const char* sample =
   15471             :     "var rv = {};"      \
   15472             :     "rv.alpha = 'hello';" \
   15473             :     "rv.beta = 123;"     \
   15474             :     "rv;";
   15475             : 
   15476             :   // Create an object, verify basics.
   15477             :   Local<Value> val = CompileRun(sample);
   15478           5 :   CHECK(val->IsObject());
   15479             :   Local<v8::Object> obj = val.As<v8::Object>();
   15480          20 :   obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
   15481             : 
   15482          25 :   CHECK(v8_str("hello")
   15483             :             ->Equals(env.local(),
   15484             :                      obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   15485             :             .FromJust());
   15486          25 :   CHECK(v8::Integer::New(isolate, 123)
   15487             :             ->Equals(env.local(),
   15488             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15489             :             .FromJust());
   15490          25 :   CHECK(v8_str("cloneme")
   15491             :             ->Equals(env.local(),
   15492             :                      obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   15493             :             .FromJust());
   15494             : 
   15495             :   // Clone it.
   15496           5 :   Local<v8::Object> clone = obj->Clone();
   15497          25 :   CHECK(v8_str("hello")
   15498             :             ->Equals(env.local(),
   15499             :                      clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   15500             :             .FromJust());
   15501          25 :   CHECK(v8::Integer::New(isolate, 123)
   15502             :             ->Equals(env.local(),
   15503             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15504             :             .FromJust());
   15505          25 :   CHECK(v8_str("cloneme")
   15506             :             ->Equals(env.local(),
   15507             :                      clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   15508             :             .FromJust());
   15509             : 
   15510             :   // Set a property on the clone, verify each object.
   15511          20 :   CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
   15512             :             .FromJust());
   15513          25 :   CHECK(v8::Integer::New(isolate, 123)
   15514             :             ->Equals(env.local(),
   15515             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15516             :             .FromJust());
   15517          25 :   CHECK(v8::Integer::New(isolate, 456)
   15518             :             ->Equals(env.local(),
   15519             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   15520           5 :             .FromJust());
   15521           5 : }
   15522             : 
   15523             : 
   15524             : class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   15525             :  public:
   15526             :   explicit OneByteVectorResource(i::Vector<const char> vector)
   15527           6 :       : data_(vector) {}
   15528           6 :   ~OneByteVectorResource() override = default;
   15529          48 :   size_t length() const override { return data_.length(); }
   15530          26 :   const char* data() const override { return data_.start(); }
   15531           0 :   void Dispose() override {}
   15532             : 
   15533             :  private:
   15534             :   i::Vector<const char> data_;
   15535             : };
   15536             : 
   15537             : 
   15538             : class UC16VectorResource : public v8::String::ExternalStringResource {
   15539             :  public:
   15540             :   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   15541          11 :       : data_(vector) {}
   15542           6 :   ~UC16VectorResource() override = default;
   15543          24 :   size_t length() const override { return data_.length(); }
   15544         416 :   const i::uc16* data() const override { return data_.start(); }
   15545           0 :   void Dispose() override {}
   15546             : 
   15547             :  private:
   15548             :   i::Vector<const i::uc16> data_;
   15549             : };
   15550             : 
   15551          12 : static void MorphAString(i::String string,
   15552             :                          OneByteVectorResource* one_byte_resource,
   15553             :                          UC16VectorResource* uc16_resource) {
   15554             :   i::Isolate* isolate = CcTest::i_isolate();
   15555          12 :   CHECK(i::StringShape(string).IsExternal());
   15556          12 :   i::ReadOnlyRoots roots(CcTest::heap());
   15557          12 :   if (string->IsOneByteRepresentation()) {
   15558             :     // Check old map is not internalized or long.
   15559          12 :     CHECK(string->map() == roots.external_one_byte_string_map());
   15560             :     // Morph external string to be TwoByte string.
   15561          12 :     string->set_map(roots.external_string_map());
   15562          12 :     i::ExternalTwoByteString morphed = i::ExternalTwoByteString::cast(string);
   15563          12 :     CcTest::heap()->UpdateExternalString(morphed, string->length(), 0);
   15564          12 :     morphed->SetResource(isolate, uc16_resource);
   15565             :   } else {
   15566             :     // Check old map is not internalized or long.
   15567           0 :     CHECK(string->map() == roots.external_string_map());
   15568             :     // Morph external string to be one-byte string.
   15569           0 :     string->set_map(roots.external_one_byte_string_map());
   15570           0 :     i::ExternalOneByteString morphed = i::ExternalOneByteString::cast(string);
   15571           0 :     CcTest::heap()->UpdateExternalString(morphed, string->length(), 0);
   15572           0 :     morphed->SetResource(isolate, one_byte_resource);
   15573             :   }
   15574          12 : }
   15575             : 
   15576             : // Test that we can still flatten a string if the components it is built up
   15577             : // from have been turned into 16 bit strings in the mean time.
   15578       28343 : THREADED_TEST(MorphCompositeStringTest) {
   15579             :   char utf_buffer[129];
   15580             :   const char* c_string = "Now is the time for all good men"
   15581             :                          " to come to the aid of the party";
   15582           6 :   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   15583             :   {
   15584           6 :     LocalContext env;
   15585             :     i::Factory* factory = CcTest::i_isolate()->factory();
   15586           6 :     v8::Isolate* isolate = env->GetIsolate();
   15587             :     i::Isolate* i_isolate = CcTest::i_isolate();
   15588          12 :     v8::HandleScope scope(isolate);
   15589             :     OneByteVectorResource one_byte_resource(
   15590             :         i::Vector<const char>(c_string, i::StrLength(c_string)));
   15591             :     UC16VectorResource uc16_resource(
   15592             :         i::Vector<const uint16_t>(two_byte_string, i::StrLength(c_string)));
   15593             : 
   15594             :     Local<String> lhs(v8::Utils::ToLocal(
   15595             :         factory->NewExternalStringFromOneByte(&one_byte_resource)
   15596          12 :             .ToHandleChecked()));
   15597             :     Local<String> rhs(v8::Utils::ToLocal(
   15598             :         factory->NewExternalStringFromOneByte(&one_byte_resource)
   15599          12 :             .ToHandleChecked()));
   15600             : 
   15601          30 :     CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
   15602          30 :     CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
   15603             : 
   15604             :     CompileRun(
   15605             :         "var cons = lhs + rhs;"
   15606             :         "var slice = lhs.substring(1, lhs.length - 1);"
   15607             :         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   15608             : 
   15609           6 :     CHECK(lhs->IsOneByte());
   15610           6 :     CHECK(rhs->IsOneByte());
   15611             : 
   15612           6 :     i::String ilhs = *v8::Utils::OpenHandle(*lhs);
   15613           6 :     i::String irhs = *v8::Utils::OpenHandle(*rhs);
   15614           6 :     MorphAString(ilhs, &one_byte_resource, &uc16_resource);
   15615           6 :     MorphAString(irhs, &one_byte_resource, &uc16_resource);
   15616             : 
   15617             :     // This should UTF-8 without flattening, since everything is ASCII.
   15618             :     Local<String> cons =
   15619          12 :         v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
   15620           6 :     CHECK_EQ(128, cons->Utf8Length(isolate));
   15621           6 :     int nchars = -1;
   15622           6 :     CHECK_EQ(129, cons->WriteUtf8(isolate, utf_buffer, -1, &nchars));
   15623           6 :     CHECK_EQ(128, nchars);
   15624           6 :     CHECK_EQ(0, strcmp(
   15625             :         utf_buffer,
   15626             :         "Now is the time for all good men to come to the aid of the party"
   15627             :         "Now is the time for all good men to come to the aid of the party"));
   15628             : 
   15629             :     // Now do some stuff to make sure the strings are flattened, etc.
   15630             :     CompileRun(
   15631             :         "/[^a-z]/.test(cons);"
   15632             :         "/[^a-z]/.test(slice);"
   15633             :         "/[^a-z]/.test(slice_on_cons);");
   15634             :     const char* expected_cons =
   15635             :         "Now is the time for all good men to come to the aid of the party"
   15636             :         "Now is the time for all good men to come to the aid of the party";
   15637             :     const char* expected_slice =
   15638             :         "ow is the time for all good men to come to the aid of the part";
   15639             :     const char* expected_slice_on_cons =
   15640             :         "ow is the time for all good men to come to the aid of the party"
   15641             :         "Now is the time for all good men to come to the aid of the part";
   15642          42 :     CHECK(v8_str(expected_cons)
   15643             :               ->Equals(env.local(), env->Global()
   15644             :                                         ->Get(env.local(), v8_str("cons"))
   15645             :                                         .ToLocalChecked())
   15646             :               .FromJust());
   15647          42 :     CHECK(v8_str(expected_slice)
   15648             :               ->Equals(env.local(), env->Global()
   15649             :                                         ->Get(env.local(), v8_str("slice"))
   15650             :                                         .ToLocalChecked())
   15651             :               .FromJust());
   15652          42 :     CHECK(v8_str(expected_slice_on_cons)
   15653             :               ->Equals(env.local(),
   15654             :                        env->Global()
   15655             :                            ->Get(env.local(), v8_str("slice_on_cons"))
   15656             :                            .ToLocalChecked())
   15657             :               .FromJust());
   15658             : 
   15659             :     // This avoids the GC from trying to free a stack allocated resource.
   15660           6 :     if (ilhs->IsExternalOneByteString())
   15661           0 :       i::ExternalOneByteString::cast(ilhs)->SetResource(i_isolate, nullptr);
   15662             :     else
   15663           6 :       i::ExternalTwoByteString::cast(ilhs)->SetResource(i_isolate, nullptr);
   15664           6 :     if (irhs->IsExternalOneByteString())
   15665           0 :       i::ExternalOneByteString::cast(irhs)->SetResource(i_isolate, nullptr);
   15666             :     else
   15667          12 :       i::ExternalTwoByteString::cast(irhs)->SetResource(i_isolate, nullptr);
   15668             :   }
   15669             :   i::DeleteArray(two_byte_string);
   15670           6 : }
   15671             : 
   15672             : 
   15673       28342 : TEST(CompileExternalTwoByteSource) {
   15674           5 :   LocalContext context;
   15675          10 :   v8::HandleScope scope(context->GetIsolate());
   15676             : 
   15677             :   // This is a very short list of sources, which currently is to check for a
   15678             :   // regression caused by r2703.
   15679             :   const char* one_byte_sources[] = {
   15680             :       "0.5",
   15681             :       "-0.5",   // This mainly testes PushBack in the Scanner.
   15682             :       "--0.5",  // This mainly testes PushBack in the Scanner.
   15683           5 :       nullptr};
   15684             : 
   15685             :   // Compile the sources as external two byte strings.
   15686          20 :   for (int i = 0; one_byte_sources[i] != nullptr; i++) {
   15687          15 :     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15688          15 :     TestResource* uc16_resource = new TestResource(two_byte_string);
   15689             :     v8::Local<v8::String> source =
   15690          15 :         v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
   15691          30 :             .ToLocalChecked();
   15692          15 :     v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
   15693           5 :   }
   15694           5 : }
   15695             : 
   15696             : 
   15697             : #ifndef V8_INTERPRETED_REGEXP
   15698             : 
   15699       28337 : struct RegExpInterruptionData {
   15700             :   v8::base::Atomic32 loop_count;
   15701             :   UC16VectorResource* string_resource;
   15702             :   v8::Persistent<v8::String> string;
   15703       28337 : } regexp_interruption_data;
   15704             : 
   15705             : 
   15706           5 : class RegExpInterruptionThread : public v8::base::Thread {
   15707             :  public:
   15708             :   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   15709           5 :       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
   15710             : 
   15711           5 :   void Run() override {
   15712          40 :     for (v8::base::Relaxed_Store(&regexp_interruption_data.loop_count, 0);
   15713             :          v8::base::Relaxed_Load(&regexp_interruption_data.loop_count) < 7;
   15714             :          v8::base::Relaxed_AtomicIncrement(&regexp_interruption_data.loop_count,
   15715             :                                            1)) {
   15716             :       // Wait a bit before requesting GC.
   15717          35 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15718          35 :       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   15719             :     }
   15720             :     // Wait a bit before terminating.
   15721           5 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15722           5 :     isolate_->TerminateExecution();
   15723           5 :   }
   15724             : 
   15725             :  private:
   15726             :   v8::Isolate* isolate_;
   15727             : };
   15728             : 
   15729             : 
   15730           2 : void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
   15731             :                  v8::GCCallbackFlags flags) {
   15732           2 :   if (v8::base::Relaxed_Load(&regexp_interruption_data.loop_count) != 2) {
   15733           2 :     return;
   15734             :   }
   15735           0 :   v8::HandleScope scope(isolate);
   15736             :   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   15737           0 :       CcTest::isolate(), regexp_interruption_data.string);
   15738           0 :   string->MakeExternal(regexp_interruption_data.string_resource);
   15739             : }
   15740             : 
   15741             : 
   15742             : // Test that RegExp execution can be interrupted.  Specifically, we test
   15743             : // * interrupting with GC
   15744             : // * turn the subject string from one-byte internal to two-byte external string
   15745             : // * force termination
   15746       28342 : TEST(RegExpInterruption) {
   15747           5 :   LocalContext env;
   15748          10 :   v8::HandleScope scope(env->GetIsolate());
   15749             : 
   15750           5 :   RegExpInterruptionThread timeout_thread(env->GetIsolate());
   15751             : 
   15752           5 :   env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
   15753             :   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   15754           5 :   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
   15755           5 :   v8::Local<v8::String> string = v8_str(one_byte_content);
   15756             : 
   15757          25 :   env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
   15758           5 :   regexp_interruption_data.string.Reset(env->GetIsolate(), string);
   15759             :   regexp_interruption_data.string_resource = new UC16VectorResource(
   15760          15 :       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
   15761             : 
   15762          10 :   v8::TryCatch try_catch(env->GetIsolate());
   15763           5 :   timeout_thread.Start();
   15764             : 
   15765             :   CompileRun("/((a*)*)*b/.exec(a)");
   15766           5 :   CHECK(try_catch.HasTerminated());
   15767             : 
   15768           5 :   timeout_thread.Join();
   15769             : 
   15770             :   regexp_interruption_data.string.Reset();
   15771           5 :   i::DeleteArray(uc16_content);
   15772           5 : }
   15773             : 
   15774             : #endif  // V8_INTERPRETED_REGEXP
   15775             : 
   15776             : 
   15777             : // Test that we cannot set a property on the global object if there
   15778             : // is a read-only property in the prototype chain.
   15779       28342 : TEST(ReadOnlyPropertyInGlobalProto) {
   15780           5 :   v8::Isolate* isolate = CcTest::isolate();
   15781           5 :   v8::HandleScope scope(isolate);
   15782           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15783          10 :   LocalContext context(nullptr, templ);
   15784           5 :   v8::Local<v8::Object> global = context->Global();
   15785             :   v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
   15786          20 :       global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
   15787             :   global_proto->DefineOwnProperty(context.local(), v8_str("x"),
   15788          20 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15789          10 :       .FromJust();
   15790             :   global_proto->DefineOwnProperty(context.local(), v8_str("y"),
   15791          20 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15792          10 :       .FromJust();
   15793             :   // Check without 'eval' or 'with'.
   15794             :   v8::Local<v8::Value> res =
   15795           5 :       CompileRun("function f() { x = 42; return x; }; f()");
   15796          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15797             :   // Check with 'eval'.
   15798           5 :   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15799          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15800             :   // Check with 'with'.
   15801           5 :   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15802          20 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15803           5 : }
   15804             : 
   15805             : 
   15806       28342 : TEST(CreateDataProperty) {
   15807           5 :   LocalContext env;
   15808           5 :   v8::Isolate* isolate = env->GetIsolate();
   15809          10 :   v8::HandleScope handle_scope(isolate);
   15810             : 
   15811             :   CompileRun(
   15812             :       "var a = {};"
   15813             :       "var b = [];"
   15814             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15815             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15816             : 
   15817             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15818          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15819             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15820          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15821             :   {
   15822             :     // Can't change a non-configurable properties.
   15823           5 :     v8::TryCatch try_catch(isolate);
   15824          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
   15825             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15826           5 :     CHECK(!try_catch.HasCaught());
   15827          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
   15828             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15829           5 :     CHECK(!try_catch.HasCaught());
   15830             :     v8::Local<v8::Value> val =
   15831          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15832           5 :     CHECK(val->IsNumber());
   15833          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15834             :   }
   15835             : 
   15836             :   {
   15837             :     // Set a regular property.
   15838           5 :     v8::TryCatch try_catch(isolate);
   15839          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
   15840             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15841           5 :     CHECK(!try_catch.HasCaught());
   15842             :     v8::Local<v8::Value> val =
   15843          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15844           5 :     CHECK(val->IsNumber());
   15845          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15846             :   }
   15847             : 
   15848             :   {
   15849             :     // Set an indexed property.
   15850           5 :     v8::TryCatch try_catch(isolate);
   15851          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
   15852             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15853           5 :     CHECK(!try_catch.HasCaught());
   15854           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15855           5 :     CHECK(val->IsNumber());
   15856          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15857             :   }
   15858             : 
   15859             :   {
   15860             :     // Special cases for arrays.
   15861           5 :     v8::TryCatch try_catch(isolate);
   15862          20 :     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
   15863             :                                    v8::Integer::New(isolate, 1)).FromJust());
   15864           5 :     CHECK(!try_catch.HasCaught());
   15865             :   }
   15866             :   {
   15867             :     // Special cases for arrays: index exceeds the array's length
   15868           5 :     v8::TryCatch try_catch(isolate);
   15869          15 :     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
   15870             :               .FromJust());
   15871           5 :     CHECK(!try_catch.HasCaught());
   15872           5 :     CHECK_EQ(2U, arr->Length());
   15873           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15874           5 :     CHECK(val->IsNumber());
   15875          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15876             : 
   15877             :     // Set an existing entry.
   15878          15 :     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
   15879             :               .FromJust());
   15880           5 :     CHECK(!try_catch.HasCaught());
   15881           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15882           5 :     CHECK(val->IsNumber());
   15883          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15884             :   }
   15885             : 
   15886             :   CompileRun("Object.freeze(a);");
   15887             :   {
   15888             :     // Can't change non-extensible objects.
   15889           5 :     v8::TryCatch try_catch(isolate);
   15890          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
   15891             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15892           5 :     CHECK(!try_catch.HasCaught());
   15893             :   }
   15894             : 
   15895           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15896           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15897             :   v8::Local<v8::Object> access_checked =
   15898           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15899             :   {
   15900           5 :     v8::TryCatch try_catch(isolate);
   15901          20 :     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
   15902             :                                              v8::Integer::New(isolate, 42))
   15903             :               .IsNothing());
   15904           5 :     CHECK(try_catch.HasCaught());
   15905           5 :   }
   15906           5 : }
   15907             : 
   15908             : 
   15909       28342 : TEST(DefineOwnProperty) {
   15910           5 :   LocalContext env;
   15911           5 :   v8::Isolate* isolate = env->GetIsolate();
   15912          10 :   v8::HandleScope handle_scope(isolate);
   15913             : 
   15914             :   CompileRun(
   15915             :       "var a = {};"
   15916             :       "var b = [];"
   15917             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15918             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15919             : 
   15920             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15921          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15922             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15923          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15924             :   {
   15925             :     // Can't change a non-configurable properties.
   15926           5 :     v8::TryCatch try_catch(isolate);
   15927          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
   15928             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15929           5 :     CHECK(!try_catch.HasCaught());
   15930          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
   15931             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15932           5 :     CHECK(!try_catch.HasCaught());
   15933             :     v8::Local<v8::Value> val =
   15934          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15935           5 :     CHECK(val->IsNumber());
   15936          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15937             :   }
   15938             : 
   15939             :   {
   15940             :     // Set a regular property.
   15941           5 :     v8::TryCatch try_catch(isolate);
   15942          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
   15943             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15944           5 :     CHECK(!try_catch.HasCaught());
   15945             :     v8::Local<v8::Value> val =
   15946          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15947           5 :     CHECK(val->IsNumber());
   15948          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15949             :   }
   15950             : 
   15951             :   {
   15952             :     // Set an indexed property.
   15953           5 :     v8::TryCatch try_catch(isolate);
   15954          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
   15955             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15956           5 :     CHECK(!try_catch.HasCaught());
   15957           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15958           5 :     CHECK(val->IsNumber());
   15959          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15960             :   }
   15961             : 
   15962             :   {
   15963             :     // Special cases for arrays.
   15964           5 :     v8::TryCatch try_catch(isolate);
   15965          20 :     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
   15966             :                                   v8::Integer::New(isolate, 1)).FromJust());
   15967           5 :     CHECK(!try_catch.HasCaught());
   15968             :   }
   15969             :   {
   15970             :     // Special cases for arrays: index exceeds the array's length
   15971           5 :     v8::TryCatch try_catch(isolate);
   15972          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
   15973             :                                  v8::Integer::New(isolate, 23)).FromJust());
   15974           5 :     CHECK(!try_catch.HasCaught());
   15975           5 :     CHECK_EQ(2U, arr->Length());
   15976           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15977           5 :     CHECK(val->IsNumber());
   15978          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15979             : 
   15980             :     // Set an existing entry.
   15981          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
   15982             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15983           5 :     CHECK(!try_catch.HasCaught());
   15984           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15985           5 :     CHECK(val->IsNumber());
   15986          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15987             :   }
   15988             : 
   15989             :   {
   15990             :     // Set a non-writable property.
   15991           5 :     v8::TryCatch try_catch(isolate);
   15992          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
   15993             :                                  v8::Integer::New(isolate, 42),
   15994             :                                  v8::ReadOnly).FromJust());
   15995           5 :     CHECK(!try_catch.HasCaught());
   15996             :     v8::Local<v8::Value> val =
   15997          15 :         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
   15998           5 :     CHECK(val->IsNumber());
   15999          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16000          15 :     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
   16001             :                                     env.local(), v8_str("lala")).FromJust());
   16002           5 :     CHECK(!try_catch.HasCaught());
   16003             :   }
   16004             : 
   16005             :   CompileRun("Object.freeze(a);");
   16006             :   {
   16007             :     // Can't change non-extensible objects.
   16008           5 :     v8::TryCatch try_catch(isolate);
   16009          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
   16010             :                                   v8::Integer::New(isolate, 42)).FromJust());
   16011           5 :     CHECK(!try_catch.HasCaught());
   16012             :   }
   16013             : 
   16014           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   16015           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   16016             :   v8::Local<v8::Object> access_checked =
   16017           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   16018             :   {
   16019           5 :     v8::TryCatch try_catch(isolate);
   16020          20 :     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
   16021             :                                             v8::Integer::New(isolate, 42))
   16022             :               .IsNothing());
   16023           5 :     CHECK(try_catch.HasCaught());
   16024           5 :   }
   16025           5 : }
   16026             : 
   16027       28342 : TEST(DefineProperty) {
   16028           5 :   LocalContext env;
   16029           5 :   v8::Isolate* isolate = env->GetIsolate();
   16030          10 :   v8::HandleScope handle_scope(isolate);
   16031             : 
   16032             :   v8::Local<v8::Name> p;
   16033             : 
   16034             :   CompileRun(
   16035             :       "var a = {};"
   16036             :       "var b = [];"
   16037             :       "Object.defineProperty(a, 'v1', {value: 23});"
   16038             :       "Object.defineProperty(a, 'v2', {value: 23, configurable: true});");
   16039             : 
   16040             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   16041          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   16042             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   16043          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   16044             : 
   16045          10 :   v8::PropertyDescriptor desc(v8_num(42));
   16046             :   {
   16047             :     // Use a data descriptor.
   16048             : 
   16049             :     // Cannot change a non-configurable property.
   16050           5 :     p = v8_str("v1");
   16051           5 :     v8::TryCatch try_catch(isolate);
   16052          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc).FromJust());
   16053           5 :     CHECK(!try_catch.HasCaught());
   16054          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16055           5 :     CHECK(val->IsNumber());
   16056          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   16057             : 
   16058             :     // Change a configurable property.
   16059           5 :     p = v8_str("v2");
   16060          10 :     obj->DefineProperty(env.local(), p, desc).FromJust();
   16061          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16062           5 :     CHECK(!try_catch.HasCaught());
   16063          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16064           5 :     CHECK(val->IsNumber());
   16065          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16066             : 
   16067             :     // Check that missing writable has default value false.
   16068           5 :     p = v8_str("v12");
   16069          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16070           5 :     CHECK(!try_catch.HasCaught());
   16071          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16072           5 :     CHECK(val->IsNumber());
   16073          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16074          10 :     v8::PropertyDescriptor desc2(v8_num(43));
   16075          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc2).FromJust());
   16076          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16077          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16078          10 :     CHECK(!try_catch.HasCaught());
   16079             :   }
   16080             : 
   16081             :   {
   16082             :     // Set a regular property.
   16083           5 :     p = v8_str("v3");
   16084           5 :     v8::TryCatch try_catch(isolate);
   16085          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16086           5 :     CHECK(!try_catch.HasCaught());
   16087          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16088           5 :     CHECK(val->IsNumber());
   16089          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16090             :   }
   16091             : 
   16092             :   {
   16093             :     // Set an indexed property.
   16094           5 :     v8::TryCatch try_catch(isolate);
   16095          15 :     CHECK(obj->DefineProperty(env.local(), v8_str("1"), desc).FromJust());
   16096           5 :     CHECK(!try_catch.HasCaught());
   16097           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   16098           5 :     CHECK(val->IsNumber());
   16099          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16100             :   }
   16101             : 
   16102             :   {
   16103             :     // No special case when changing array length.
   16104           5 :     v8::TryCatch try_catch(isolate);
   16105             :     // Use a writable descriptor, otherwise the next test, that changes
   16106             :     // the array length will fail.
   16107          10 :     v8::PropertyDescriptor desc(v8_num(42), true);
   16108          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("length"), desc).FromJust());
   16109          10 :     CHECK(!try_catch.HasCaught());
   16110             :   }
   16111             : 
   16112             :   {
   16113             :     // Special cases for arrays: index exceeds the array's length.
   16114           5 :     v8::TryCatch try_catch(isolate);
   16115          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("100"), desc).FromJust());
   16116           5 :     CHECK(!try_catch.HasCaught());
   16117           5 :     CHECK_EQ(101U, arr->Length());
   16118           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 100).ToLocalChecked();
   16119           5 :     CHECK(val->IsNumber());
   16120          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16121             : 
   16122             :     // Set an existing entry.
   16123          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("0"), desc).FromJust());
   16124           5 :     CHECK(!try_catch.HasCaught());
   16125           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   16126           5 :     CHECK(val->IsNumber());
   16127          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16128             :   }
   16129             : 
   16130             :   {
   16131             :     // Use a generic descriptor.
   16132           5 :     v8::PropertyDescriptor desc_generic;
   16133             : 
   16134           5 :     p = v8_str("v4");
   16135          10 :     v8::TryCatch try_catch(isolate);
   16136          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_generic).FromJust());
   16137           5 :     CHECK(!try_catch.HasCaught());
   16138          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16139           5 :     CHECK(val->IsUndefined());
   16140             : 
   16141          15 :     obj->Set(env.local(), p, v8_num(1)).FromJust();
   16142           5 :     CHECK(!try_catch.HasCaught());
   16143             : 
   16144          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16145           5 :     CHECK(val->IsUndefined());
   16146          10 :     CHECK(!try_catch.HasCaught());
   16147             :   }
   16148             : 
   16149             :   {
   16150             :     // Use a data descriptor with undefined value.
   16151           5 :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate));
   16152             : 
   16153          10 :     v8::TryCatch try_catch(isolate);
   16154          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16155           5 :     CHECK(!try_catch.HasCaught());
   16156          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16157           5 :     CHECK(val->IsUndefined());
   16158          10 :     CHECK(!try_catch.HasCaught());
   16159             :   }
   16160             : 
   16161             :   {
   16162             :     // Use a descriptor with attribute == v8::ReadOnly.
   16163           5 :     v8::PropertyDescriptor desc_read_only(v8_num(42), false);
   16164           5 :     desc_read_only.set_enumerable(true);
   16165           5 :     desc_read_only.set_configurable(true);
   16166             : 
   16167           5 :     p = v8_str("v5");
   16168          10 :     v8::TryCatch try_catch(isolate);
   16169          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_read_only).FromJust());
   16170           5 :     CHECK(!try_catch.HasCaught());
   16171          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16172           5 :     CHECK(val->IsNumber());
   16173          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   16174          10 :     CHECK_EQ(v8::ReadOnly,
   16175             :              obj->GetPropertyAttributes(env.local(), p).FromJust());
   16176          10 :     CHECK(!try_catch.HasCaught());
   16177             :   }
   16178             : 
   16179             :   {
   16180             :     // Use an accessor descriptor with empty handles.
   16181             :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate),
   16182           5 :                                       v8::Undefined(isolate));
   16183             : 
   16184           5 :     p = v8_str("v6");
   16185          10 :     v8::TryCatch try_catch(isolate);
   16186          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16187           5 :     CHECK(!try_catch.HasCaught());
   16188          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16189           5 :     CHECK(val->IsUndefined());
   16190          10 :     CHECK(!try_catch.HasCaught());
   16191             :   }
   16192             : 
   16193             :   {
   16194             :     // Use an accessor descriptor.
   16195             :     CompileRun(
   16196             :         "var set = function(x) {this.val = 2*x;};"
   16197             :         "var get = function() {return this.val || 0;};");
   16198             : 
   16199             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   16200          25 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   16201             :     v8::Local<v8::Function> set = v8::Local<v8::Function>::Cast(
   16202          25 :         env->Global()->Get(env.local(), v8_str("set")).ToLocalChecked());
   16203           5 :     v8::PropertyDescriptor desc(get, set);
   16204             : 
   16205           5 :     p = v8_str("v7");
   16206          10 :     v8::TryCatch try_catch(isolate);
   16207          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16208           5 :     CHECK(!try_catch.HasCaught());
   16209             : 
   16210          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   16211           5 :     CHECK(val->IsNumber());
   16212          10 :     CHECK_EQ(0.0, val->NumberValue(env.local()).FromJust());
   16213           5 :     CHECK(!try_catch.HasCaught());
   16214             : 
   16215          15 :     obj->Set(env.local(), p, v8_num(7)).FromJust();
   16216           5 :     CHECK(!try_catch.HasCaught());
   16217             : 
   16218          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   16219           5 :     CHECK(val->IsNumber());
   16220          10 :     CHECK_EQ(14.0, val->NumberValue(env.local()).FromJust());
   16221          10 :     CHECK(!try_catch.HasCaught());
   16222             :   }
   16223             : 
   16224             :   {
   16225             :     // Redefine an existing property.
   16226             : 
   16227             :     // desc = {value: 42, enumerable: true}
   16228           5 :     v8::PropertyDescriptor desc(v8_num(42));
   16229           5 :     desc.set_enumerable(true);
   16230             : 
   16231           5 :     p = v8_str("v8");
   16232          10 :     v8::TryCatch try_catch(isolate);
   16233          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16234           5 :     CHECK(!try_catch.HasCaught());
   16235             : 
   16236             :     // desc = {enumerable: true}
   16237          10 :     v8::PropertyDescriptor desc_true((v8::Local<v8::Value>()));
   16238           5 :     desc_true.set_enumerable(true);
   16239             : 
   16240             :     // Successful redefinition because all present attributes have the same
   16241             :     // value as the current descriptor.
   16242          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_true).FromJust());
   16243           5 :     CHECK(!try_catch.HasCaught());
   16244             : 
   16245             :     // desc = {}
   16246          10 :     v8::PropertyDescriptor desc_empty;
   16247             :     // Successful redefinition because no attributes are overwritten in the
   16248             :     // current descriptor.
   16249          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16250           5 :     CHECK(!try_catch.HasCaught());
   16251             : 
   16252             :     // desc = {enumerable: false}
   16253          10 :     v8::PropertyDescriptor desc_false((v8::Local<v8::Value>()));
   16254           5 :     desc_false.set_enumerable(false);
   16255             :     // Not successful because we cannot define a different value for enumerable.
   16256          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_false).FromJust());
   16257          10 :     CHECK(!try_catch.HasCaught());
   16258             :   }
   16259             : 
   16260             :   {
   16261             :     // Redefine a property that has a getter.
   16262             :     CompileRun("var get = function() {};");
   16263             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   16264          25 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   16265             : 
   16266             :     // desc = {get: function() {}}
   16267           5 :     v8::PropertyDescriptor desc(get, v8::Local<v8::Function>());
   16268          10 :     v8::TryCatch try_catch(isolate);
   16269             : 
   16270           5 :     p = v8_str("v9");
   16271          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16272           5 :     CHECK(!try_catch.HasCaught());
   16273             : 
   16274             :     // desc_empty = {}
   16275             :     // Successful because we are not redefining the current getter.
   16276          10 :     v8::PropertyDescriptor desc_empty;
   16277          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   16278           5 :     CHECK(!try_catch.HasCaught());
   16279             : 
   16280             :     // desc = {get: function() {}}
   16281             :     // Successful because we redefine the getter with its current value.
   16282          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   16283           5 :     CHECK(!try_catch.HasCaught());
   16284             : 
   16285             :     // desc = {get: undefined}
   16286             :     v8::PropertyDescriptor desc_undefined(v8::Undefined(isolate),
   16287          10 :                                           v8::Local<v8::Function>());
   16288             :     // Not successful because we cannot redefine with the current value of get
   16289             :     // with undefined.
   16290          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_undefined).FromJust());
   16291          10 :     CHECK(!try_catch.HasCaught());
   16292             :   }
   16293             : 
   16294             :   CompileRun("Object.freeze(a);");
   16295             :   {
   16296             :     // We cannot change non-extensible objects.
   16297           5 :     v8::TryCatch try_catch(isolate);
   16298          15 :     CHECK(!obj->DefineProperty(env.local(), v8_str("v10"), desc).FromJust());
   16299           5 :     CHECK(!try_catch.HasCaught());
   16300             :   }
   16301             : 
   16302           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   16303           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   16304             :   v8::Local<v8::Object> access_checked =
   16305           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   16306             :   {
   16307           5 :     v8::TryCatch try_catch(isolate);
   16308          15 :     CHECK(access_checked->DefineProperty(env.local(), v8_str("v11"), desc)
   16309             :               .IsNothing());
   16310           5 :     CHECK(try_catch.HasCaught());
   16311           5 :   }
   16312           5 : }
   16313             : 
   16314       28343 : THREADED_TEST(GetCurrentContextWhenNotInContext) {
   16315             :   i::Isolate* isolate = CcTest::i_isolate();
   16316           6 :   CHECK_NOT_NULL(isolate);
   16317           6 :   CHECK(isolate->context().is_null());
   16318             :   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   16319           6 :   v8::HandleScope scope(v8_isolate);
   16320             :   // The following should not crash, but return an empty handle.
   16321           6 :   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   16322           6 :   CHECK(current.IsEmpty());
   16323           6 : }
   16324             : 
   16325             : 
   16326             : // Check that a variable declaration with no explicit initialization
   16327             : // value does shadow an existing property in the prototype chain.
   16328       28343 : THREADED_TEST(InitGlobalVarInProtoChain) {
   16329           6 :   LocalContext context;
   16330          12 :   v8::HandleScope scope(context->GetIsolate());
   16331             :   // Introduce a variable in the prototype chain.
   16332             :   CompileRun("__proto__.x = 42");
   16333             :   v8::Local<v8::Value> result = CompileRun("var x = 43; x");
   16334           6 :   CHECK(!result->IsUndefined());
   16335          18 :   CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
   16336           6 : }
   16337             : 
   16338             : 
   16339             : // Regression test for issue 398.
   16340             : // If a function is added to an object, creating a constant function
   16341             : // field, and the result is cloned, replacing the constant function on the
   16342             : // original should not affect the clone.
   16343             : // See http://code.google.com/p/v8/issues/detail?id=398
   16344       28343 : THREADED_TEST(ReplaceConstantFunction) {
   16345           6 :   LocalContext context;
   16346           6 :   v8::Isolate* isolate = context->GetIsolate();
   16347          12 :   v8::HandleScope scope(isolate);
   16348           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   16349             :   v8::Local<v8::FunctionTemplate> func_templ =
   16350           6 :       v8::FunctionTemplate::New(isolate);
   16351           6 :   v8::Local<v8::String> foo_string = v8_str("foo");
   16352             :   obj->Set(context.local(), foo_string,
   16353          24 :            func_templ->GetFunction(context.local()).ToLocalChecked())
   16354          12 :       .FromJust();
   16355           6 :   v8::Local<v8::Object> obj_clone = obj->Clone();
   16356          24 :   obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
   16357          18 :   CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
   16358           6 : }
   16359             : 
   16360             : 
   16361         504 : static void CheckElementValue(i::Isolate* isolate,
   16362             :                               int expected,
   16363             :                               i::Handle<i::Object> obj,
   16364             :                               int offset) {
   16365             :   i::Object element =
   16366        1008 :       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   16367         504 :   CHECK_EQ(expected, i::Smi::ToInt(element));
   16368         504 : }
   16369             : 
   16370             : 
   16371             : template <class ExternalArrayClass, class ElementType>
   16372         162 : static void ObjectWithExternalArrayTestHelper(Local<Context> context,
   16373             :                                               v8::Local<Object> obj,
   16374             :                                               int element_count,
   16375             :                                               i::ExternalArrayType array_type,
   16376             :                                               int64_t low, int64_t high) {
   16377             :   i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
   16378         162 :   v8::Isolate* v8_isolate = context->GetIsolate();
   16379             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
   16380         486 :   obj->Set(context, v8_str("field"), v8::Int32::New(v8_isolate, 1503))
   16381         324 :       .FromJust();
   16382         648 :   CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
   16383             :   v8::Local<v8::Value> result = CompileRun("ext_array.field");
   16384         324 :   CHECK_EQ(1503, result->Int32Value(context).FromJust());
   16385             :   result = CompileRun("ext_array[1]");
   16386         324 :   CHECK_EQ(1, result->Int32Value(context).FromJust());
   16387             : 
   16388             :   // Check assigned smis
   16389             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16390             :                       "  ext_array[i] = i;"
   16391             :                       "}"
   16392             :                       "var sum = 0;"
   16393             :                       "for (var i = 0; i < 8; i++) {"
   16394             :                       "  sum += ext_array[i];"
   16395             :                       "}"
   16396             :                       "sum;");
   16397             : 
   16398         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16399             :   // Check pass through of assigned smis
   16400             :   result = CompileRun("var sum = 0;"
   16401             :                       "for (var i = 0; i < 8; i++) {"
   16402             :                       "  sum += ext_array[i] = ext_array[i] = -i;"
   16403             :                       "}"
   16404             :                       "sum;");
   16405         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   16406             : 
   16407             : 
   16408             :   // Check assigned smis in reverse order
   16409             :   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   16410             :                       "  ext_array[i] = i;"
   16411             :                       "}"
   16412             :                       "var sum = 0;"
   16413             :                       "for (var i = 0; i < 8; i++) {"
   16414             :                       "  sum += ext_array[i];"
   16415             :                       "}"
   16416             :                       "sum;");
   16417         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16418             : 
   16419             :   // Check pass through of assigned HeapNumbers
   16420             :   result = CompileRun("var sum = 0;"
   16421             :                       "for (var i = 0; i < 16; i+=2) {"
   16422             :                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   16423             :                       "}"
   16424             :                       "sum;");
   16425         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   16426             : 
   16427             :   // Check assigned HeapNumbers
   16428             :   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   16429             :                       "  ext_array[i] = (i * 0.5);"
   16430             :                       "}"
   16431             :                       "var sum = 0;"
   16432             :                       "for (var i = 0; i < 16; i+=2) {"
   16433             :                       "  sum += ext_array[i];"
   16434             :                       "}"
   16435             :                       "sum;");
   16436         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16437             : 
   16438             :   // Check assigned HeapNumbers in reverse order
   16439             :   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   16440             :                       "  ext_array[i] = (i * 0.5);"
   16441             :                       "}"
   16442             :                       "var sum = 0;"
   16443             :                       "for (var i = 0; i < 16; i+=2) {"
   16444             :                       "  sum += ext_array[i];"
   16445             :                       "}"
   16446             :                       "sum;");
   16447         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16448             : 
   16449             :   i::ScopedVector<char> test_buf(1024);
   16450             : 
   16451             :   // Check legal boundary conditions.
   16452             :   // The repeated loads and stores ensure the ICs are exercised.
   16453             :   const char* boundary_program =
   16454             :       "var res = 0;"
   16455             :       "for (var i = 0; i < 16; i++) {"
   16456             :       "  ext_array[i] = %lld;"
   16457             :       "  if (i > 8) {"
   16458             :       "    res = ext_array[i];"
   16459             :       "  }"
   16460             :       "}"
   16461             :       "res;";
   16462         162 :   i::SNPrintF(test_buf,
   16463             :               boundary_program,
   16464             :               low);
   16465             :   result = CompileRun(test_buf.start());
   16466         324 :   CHECK_EQ(low, result->IntegerValue(context).FromJust());
   16467             : 
   16468         162 :   i::SNPrintF(test_buf,
   16469             :               boundary_program,
   16470             :               high);
   16471             :   result = CompileRun(test_buf.start());
   16472         324 :   CHECK_EQ(high, result->IntegerValue(context).FromJust());
   16473             : 
   16474             :   // Check misprediction of type in IC.
   16475             :   result = CompileRun("var tmp_array = ext_array;"
   16476             :                       "var sum = 0;"
   16477             :                       "for (var i = 0; i < 8; i++) {"
   16478             :                       "  tmp_array[i] = i;"
   16479             :                       "  sum += tmp_array[i];"
   16480             :                       "  if (i == 4) {"
   16481             :                       "    tmp_array = {};"
   16482             :                       "  }"
   16483             :                       "}"
   16484             :                       "sum;");
   16485             :   // Force GC to trigger verification.
   16486         162 :   CcTest::CollectAllGarbage();
   16487         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   16488             : 
   16489             :   // Make sure out-of-range loads do not throw.
   16490         162 :   i::SNPrintF(test_buf,
   16491             :               "var caught_exception = false;"
   16492             :               "try {"
   16493             :               "  ext_array[%d];"
   16494             :               "} catch (e) {"
   16495             :               "  caught_exception = true;"
   16496             :               "}"
   16497             :               "caught_exception;",
   16498             :               element_count);
   16499             :   result = CompileRun(test_buf.start());
   16500         162 :   CHECK(!result->BooleanValue(v8_isolate));
   16501             : 
   16502             :   // Make sure out-of-range stores do not throw.
   16503         162 :   i::SNPrintF(test_buf,
   16504             :               "var caught_exception = false;"
   16505             :               "try {"
   16506             :               "  ext_array[%d] = 1;"
   16507             :               "} catch (e) {"
   16508             :               "  caught_exception = true;"
   16509             :               "}"
   16510             :               "caught_exception;",
   16511             :               element_count);
   16512             :   result = CompileRun(test_buf.start());
   16513         162 :   CHECK(!result->BooleanValue(v8_isolate));
   16514             : 
   16515             :   // Check other boundary conditions, values and operations.
   16516             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16517             :                       "  ext_array[7] = undefined;"
   16518             :                       "}"
   16519             :                       "ext_array[7];");
   16520         324 :   CHECK_EQ(0, result->Int32Value(context).FromJust());
   16521         162 :   if (array_type == i::kExternalFloat64Array ||
   16522             :       array_type == i::kExternalFloat32Array) {
   16523          72 :     CHECK(std::isnan(
   16524             :         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
   16525             :   } else {
   16526         126 :     CheckElementValue(isolate, 0, jsobj, 7);
   16527             :   }
   16528             : 
   16529             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   16530             :                       "  ext_array[6] = '2.3';"
   16531             :                       "}"
   16532             :                       "ext_array[6];");
   16533         324 :   CHECK_EQ(2, result->Int32Value(context).FromJust());
   16534         324 :   CHECK_EQ(2,
   16535             :            static_cast<int>(
   16536             :                i::Object::GetElement(
   16537             :                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   16538             : 
   16539         162 :   if (array_type != i::kExternalFloat32Array &&
   16540             :       array_type != i::kExternalFloat64Array) {
   16541             :     // Though the specification doesn't state it, be explicit about
   16542             :     // converting NaNs and +/-Infinity to zero.
   16543             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16544             :                         "  ext_array[i] = 5;"
   16545             :                         "}"
   16546             :                         "for (var i = 0; i < 8; i++) {"
   16547             :                         "  ext_array[i] = NaN;"
   16548             :                         "}"
   16549             :                         "ext_array[5];");
   16550         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   16551         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   16552             : 
   16553             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16554             :                         "  ext_array[i] = 5;"
   16555             :                         "}"
   16556             :                         "for (var i = 0; i < 8; i++) {"
   16557             :                         "  ext_array[i] = Infinity;"
   16558             :                         "}"
   16559             :                         "ext_array[5];");
   16560             :     int expected_value =
   16561         126 :         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
   16562         252 :     CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
   16563         126 :     CheckElementValue(isolate, expected_value, jsobj, 5);
   16564             : 
   16565             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   16566             :                         "  ext_array[i] = 5;"
   16567             :                         "}"
   16568             :                         "for (var i = 0; i < 8; i++) {"
   16569             :                         "  ext_array[i] = -Infinity;"
   16570             :                         "}"
   16571             :                         "ext_array[5];");
   16572         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   16573         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   16574             : 
   16575             :     // Check truncation behavior of integral arrays.
   16576             :     const char* unsigned_data =
   16577             :         "var source_data = [0.6, 10.6];"
   16578             :         "var expected_results = [0, 10];";
   16579             :     const char* signed_data =
   16580             :         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   16581             :         "var expected_results = [0, 10, 0, -10];";
   16582             :     const char* pixel_data =
   16583             :         "var source_data = [0.6, 10.6];"
   16584             :         "var expected_results = [1, 11];";
   16585             :     bool is_unsigned = (array_type == i::kExternalUint8Array ||
   16586             :                         array_type == i::kExternalUint16Array ||
   16587         126 :                         array_type == i::kExternalUint32Array);
   16588             :     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
   16589             : 
   16590         126 :     i::SNPrintF(test_buf,
   16591             :                 "%s"
   16592             :                 "var all_passed = true;"
   16593             :                 "for (var i = 0; i < source_data.length; i++) {"
   16594             :                 "  for (var j = 0; j < 8; j++) {"
   16595             :                 "    ext_array[j] = source_data[i];"
   16596             :                 "  }"
   16597             :                 "  all_passed = all_passed &&"
   16598             :                 "               (ext_array[5] == expected_results[i]);"
   16599             :                 "}"
   16600             :                 "all_passed;",
   16601             :                 (is_unsigned ?
   16602             :                      unsigned_data :
   16603         126 :                      (is_pixel_data ? pixel_data : signed_data)));
   16604             :     result = CompileRun(test_buf.start());
   16605         126 :     CHECK(result->BooleanValue(v8_isolate));
   16606             :   }
   16607             : 
   16608             :   i::Handle<ExternalArrayClass> array(
   16609         486 :       ExternalArrayClass::cast(i::Handle<i::JSObject>::cast(jsobj)->elements()),
   16610         324 :       isolate);
   16611       19602 :   for (int i = 0; i < element_count; i++) {
   16612       36720 :     array->set(i, static_cast<ElementType>(i));
   16613             :   }
   16614             : 
   16615         162 :   bool old_natives_flag_sentry = i::FLAG_allow_natives_syntax;
   16616         162 :   i::FLAG_allow_natives_syntax = true;
   16617             : 
   16618             :   // Test complex assignments
   16619             :   result = CompileRun(
   16620             :       "function ee_op_test_complex_func(sum) {"
   16621             :       " for (var i = 0; i < 40; ++i) {"
   16622             :       "   sum += (ext_array[i] += 1);"
   16623             :       "   sum += (ext_array[i] -= 1);"
   16624             :       " } "
   16625             :       " return sum;"
   16626             :       "}"
   16627             :       "sum=0;"
   16628             :       "sum=ee_op_test_complex_func(sum);"
   16629             :       "sum=ee_op_test_complex_func(sum);"
   16630             :       "%OptimizeFunctionOnNextCall(ee_op_test_complex_func);"
   16631             :       "sum=ee_op_test_complex_func(sum);"
   16632             :       "sum;");
   16633         324 :   CHECK_EQ(4800, result->Int32Value(context).FromJust());
   16634             : 
   16635             :   // Test count operations
   16636             :   result = CompileRun(
   16637             :       "function ee_op_test_count_func(sum) {"
   16638             :       " for (var i = 0; i < 40; ++i) {"
   16639             :       "   sum += (++ext_array[i]);"
   16640             :       "   sum += (--ext_array[i]);"
   16641             :       " } "
   16642             :       " return sum;"
   16643             :       "}"
   16644             :       "sum=0;"
   16645             :       "sum=ee_op_test_count_func(sum);"
   16646             :       "sum=ee_op_test_count_func(sum);"
   16647             :       "%OptimizeFunctionOnNextCall(ee_op_test_count_func);"
   16648             :       "sum=ee_op_test_count_func(sum);"
   16649             :       "sum;");
   16650         324 :   CHECK_EQ(4800, result->Int32Value(context).FromJust());
   16651             : 
   16652         162 :   i::FLAG_allow_natives_syntax = old_natives_flag_sentry;
   16653             : 
   16654             :   result = CompileRun("ext_array[3] = 33;"
   16655             :                       "delete ext_array[3];"
   16656             :                       "ext_array[3];");
   16657         324 :   CHECK_EQ(33, result->Int32Value(context).FromJust());
   16658             : 
   16659             :   result = CompileRun(
   16660             :       "ext_array[0] = 10; ext_array[1] = 11;"
   16661             :       "ext_array[2] = 12; ext_array[3] = 13;"
   16662             :       "try { ext_array.__defineGetter__('2', function() { return 120; }); }"
   16663             :       "catch (e) { }"
   16664             :       "ext_array[2];");
   16665         324 :   CHECK_EQ(12, result->Int32Value(context).FromJust());
   16666             : 
   16667             :   result = CompileRun("var js_array = new Array(40);"
   16668             :                       "js_array[0] = 77;"
   16669             :                       "js_array;");
   16670         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16671             :                    ->Get(context, v8_str("0"))
   16672             :                    .ToLocalChecked()
   16673             :                    ->Int32Value(context)
   16674             :                    .FromJust());
   16675             : 
   16676             :   result = CompileRun("ext_array[1] = 23;"
   16677             :                       "ext_array.__proto__ = [];"
   16678             :                       "js_array.__proto__ = ext_array;"
   16679             :                       "js_array.concat(ext_array);");
   16680         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16681             :                    ->Get(context, v8_str("0"))
   16682             :                    .ToLocalChecked()
   16683             :                    ->Int32Value(context)
   16684             :                    .FromJust());
   16685         648 :   CHECK_EQ(23, v8::Object::Cast(*result)
   16686             :                    ->Get(context, v8_str("1"))
   16687             :                    .ToLocalChecked()
   16688             :                    ->Int32Value(context)
   16689             :                    .FromJust());
   16690             : 
   16691             :   result = CompileRun("ext_array[1] = 23;");
   16692         324 :   CHECK_EQ(23, result->Int32Value(context).FromJust());
   16693         162 : }
   16694             : 
   16695             : 
   16696             : template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
   16697             :           class ElementType>
   16698          54 : static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
   16699             :                                       ElementType low, ElementType high) {
   16700          54 :   i::FLAG_allow_natives_syntax = true;
   16701          54 :   LocalContext context;
   16702             :   i::Isolate* isolate = CcTest::i_isolate();
   16703             :   i::Factory* factory = isolate->factory();
   16704         108 :   v8::HandleScope scope(context->GetIsolate());
   16705             :   const int kElementCount = 260;
   16706             :   i::Handle<i::JSTypedArray> jsobj =
   16707          54 :       factory->NewJSTypedArray(elements_kind, kElementCount);
   16708             :   i::Handle<FixedTypedArrayClass> fixed_array(
   16709         108 :       FixedTypedArrayClass::cast(jsobj->elements()), isolate);
   16710          54 :   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   16711             :            fixed_array->map()->instance_type());
   16712          54 :   CHECK_EQ(kElementCount, fixed_array->length());
   16713          54 :   CcTest::CollectAllGarbage();
   16714       14094 :   for (int i = 0; i < kElementCount; i++) {
   16715       26520 :     fixed_array->set(i, static_cast<ElementType>(i));
   16716             :   }
   16717             :   // Force GC to trigger verification.
   16718          54 :   CcTest::CollectAllGarbage();
   16719       14094 :   for (int i = 0; i < kElementCount; i++) {
   16720       14040 :     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   16721             :              static_cast<int64_t>(fixed_array->get_scalar(i)));
   16722             :   }
   16723             :   v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
   16724             : 
   16725          54 :   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   16726             :       context.local(), obj, kElementCount, array_type,
   16727             :       static_cast<int64_t>(low),
   16728         108 :       static_cast<int64_t>(high));
   16729          54 : }
   16730             : 
   16731             : 
   16732       28343 : THREADED_TEST(FixedUint8Array) {
   16733             :   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   16734           6 :       i::kExternalUint8Array, 0x0, 0xFF);
   16735           6 : }
   16736             : 
   16737             : 
   16738       28343 : THREADED_TEST(FixedUint8ClampedArray) {
   16739             :   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   16740             :                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   16741           6 :       i::kExternalUint8ClampedArray, 0x0, 0xFF);
   16742           6 : }
   16743             : 
   16744             : 
   16745       28343 : THREADED_TEST(FixedInt8Array) {
   16746             :   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   16747           6 :       i::kExternalInt8Array, -0x80, 0x7F);
   16748           6 : }
   16749             : 
   16750             : 
   16751       28343 : THREADED_TEST(FixedUint16Array) {
   16752             :   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   16753           6 :       i::kExternalUint16Array, 0x0, 0xFFFF);
   16754           6 : }
   16755             : 
   16756             : 
   16757       28343 : THREADED_TEST(FixedInt16Array) {
   16758             :   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   16759           6 :       i::kExternalInt16Array, -0x8000, 0x7FFF);
   16760           6 : }
   16761             : 
   16762             : 
   16763       28343 : THREADED_TEST(FixedUint32Array) {
   16764             :   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   16765           6 :       i::kExternalUint32Array, 0x0, UINT_MAX);
   16766           6 : }
   16767             : 
   16768             : 
   16769       28343 : THREADED_TEST(FixedInt32Array) {
   16770             :   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   16771           6 :       i::kExternalInt32Array, INT_MIN, INT_MAX);
   16772           6 : }
   16773             : 
   16774             : 
   16775       28343 : THREADED_TEST(FixedFloat32Array) {
   16776             :   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   16777           6 :       i::kExternalFloat32Array, -500, 500);
   16778           6 : }
   16779             : 
   16780             : 
   16781       28343 : THREADED_TEST(FixedFloat64Array) {
   16782             :   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   16783           6 :       i::kExternalFloat64Array, -500, 500);
   16784           6 : }
   16785             : 
   16786             : 
   16787             : template <typename ElementType, typename TypedArray, class ExternalArrayClass,
   16788             :           class ArrayBufferType>
   16789         108 : void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
   16790             :                           int64_t high) {
   16791             :   const int kElementCount = 50;
   16792             : 
   16793             :   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16794             : 
   16795         216 :   LocalContext env;
   16796         108 :   v8::Isolate* isolate = env->GetIsolate();
   16797         216 :   v8::HandleScope handle_scope(isolate);
   16798             : 
   16799             :   Local<ArrayBufferType> ab =
   16800             :       ArrayBufferType::New(isolate, backing_store.start(),
   16801         108 :                            (kElementCount + 2) * sizeof(ElementType));
   16802             :   Local<TypedArray> ta =
   16803         108 :       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16804         108 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16805         108 :   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16806         108 :   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
   16807         108 :   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
   16808         432 :   CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
   16809             : 
   16810         108 :   ElementType* data = backing_store.start() + 2;
   16811        5508 :   for (int i = 0; i < kElementCount; i++) {
   16812        5400 :     data[i] = static_cast<ElementType>(i);
   16813             :   }
   16814             : 
   16815         108 :   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16816         216 :       env.local(), ta, kElementCount, array_type, low, high);
   16817         108 : }
   16818             : 
   16819             : 
   16820       28343 : THREADED_TEST(Uint8Array) {
   16821             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16822           6 :                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16823           6 : }
   16824             : 
   16825             : 
   16826       28343 : THREADED_TEST(Int8Array) {
   16827             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16828           6 :                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
   16829           6 : }
   16830             : 
   16831             : 
   16832       28343 : THREADED_TEST(Uint16Array) {
   16833             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16834           6 :                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
   16835           6 : }
   16836             : 
   16837             : 
   16838       28343 : THREADED_TEST(Int16Array) {
   16839             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16840             :                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16841           6 :                                         0x7FFF);
   16842           6 : }
   16843             : 
   16844             : 
   16845       28343 : THREADED_TEST(Uint32Array) {
   16846             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16847           6 :                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
   16848           6 : }
   16849             : 
   16850             : 
   16851       28343 : THREADED_TEST(Int32Array) {
   16852             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16853             :                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16854           6 :                                         INT_MAX);
   16855           6 : }
   16856             : 
   16857             : 
   16858       28343 : THREADED_TEST(Float32Array) {
   16859             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16860           6 :                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
   16861           6 : }
   16862             : 
   16863             : 
   16864       28343 : THREADED_TEST(Float64Array) {
   16865             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16866           6 :                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
   16867           6 : }
   16868             : 
   16869             : 
   16870       28343 : THREADED_TEST(Uint8ClampedArray) {
   16871             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16872             :                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
   16873           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16874           6 : }
   16875             : 
   16876             : 
   16877       28343 : THREADED_TEST(DataView) {
   16878             :   const int kSize = 50;
   16879             : 
   16880             :   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16881             : 
   16882          12 :   LocalContext env;
   16883           6 :   v8::Isolate* isolate = env->GetIsolate();
   16884          12 :   v8::HandleScope handle_scope(isolate);
   16885             : 
   16886             :   Local<v8::ArrayBuffer> ab =
   16887           6 :       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16888           6 :   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
   16889           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16890           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16891           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16892          24 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16893           6 : }
   16894             : 
   16895             : 
   16896       28343 : THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
   16897           6 :   LocalContext env;
   16898           6 :   v8::Isolate* isolate = env->GetIsolate();
   16899          12 :   v8::HandleScope handle_scope(isolate);
   16900             : 
   16901             :   // Make sure the pointer looks like a heap object
   16902             :   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
   16903             : 
   16904             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16905           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16906             : 
   16907             :   // Should not crash
   16908           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16909           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16910           6 :   CcTest::CollectAllGarbage();
   16911           6 :   CcTest::CollectAllGarbage();
   16912             : 
   16913             :   // Should not move the pointer
   16914          12 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16915           6 : }
   16916             : 
   16917             : 
   16918       28343 : THREADED_TEST(SkipArrayBufferDuringScavenge) {
   16919           6 :   LocalContext env;
   16920           6 :   v8::Isolate* isolate = env->GetIsolate();
   16921          12 :   v8::HandleScope handle_scope(isolate);
   16922             : 
   16923             :   // Make sure the pointer looks like a heap object
   16924           6 :   Local<v8::Object> tmp = v8::Object::New(isolate);
   16925             :   uint8_t* store_ptr =
   16926           6 :       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
   16927             : 
   16928             :   // Make `store_ptr` point to from space
   16929           6 :   CcTest::CollectGarbage(i::NEW_SPACE);
   16930             : 
   16931             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16932           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16933             : 
   16934             :   // Should not crash,
   16935             :   // i.e. backing store pointer should not be treated as a heap object pointer
   16936           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16937           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16938             : 
   16939             :   // Use `ab` to silence compiler warning
   16940          12 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16941           6 : }
   16942             : 
   16943             : 
   16944       28343 : THREADED_TEST(SharedUint8Array) {
   16945           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16946             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16947           6 :                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16948           6 : }
   16949             : 
   16950             : 
   16951       28343 : THREADED_TEST(SharedInt8Array) {
   16952           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16953             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16954             :                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
   16955           6 :                                               0x7F);
   16956           6 : }
   16957             : 
   16958             : 
   16959       28343 : THREADED_TEST(SharedUint16Array) {
   16960           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16961             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16962             :                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
   16963           6 :                                               0xFFFF);
   16964           6 : }
   16965             : 
   16966             : 
   16967       28343 : THREADED_TEST(SharedInt16Array) {
   16968           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16969             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16970             :                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16971           6 :                                               0x7FFF);
   16972           6 : }
   16973             : 
   16974             : 
   16975       28343 : THREADED_TEST(SharedUint32Array) {
   16976           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16977             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16978             :                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
   16979           6 :                                               UINT_MAX);
   16980           6 : }
   16981             : 
   16982             : 
   16983       28343 : THREADED_TEST(SharedInt32Array) {
   16984           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16985             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16986             :                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16987           6 :                                               INT_MAX);
   16988           6 : }
   16989             : 
   16990             : 
   16991       28343 : THREADED_TEST(SharedFloat32Array) {
   16992           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16993             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16994             :                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
   16995           6 :                                               500);
   16996           6 : }
   16997             : 
   16998             : 
   16999       28343 : THREADED_TEST(SharedFloat64Array) {
   17000           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   17001             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   17002             :                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
   17003           6 :                                               500);
   17004           6 : }
   17005             : 
   17006             : 
   17007       28343 : THREADED_TEST(SharedUint8ClampedArray) {
   17008           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   17009             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   17010             :                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
   17011           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   17012           6 : }
   17013             : 
   17014             : 
   17015       28343 : THREADED_TEST(SharedDataView) {
   17016           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   17017             :   const int kSize = 50;
   17018             : 
   17019             :   i::ScopedVector<uint8_t> backing_store(kSize + 2);
   17020             : 
   17021          12 :   LocalContext env;
   17022           6 :   v8::Isolate* isolate = env->GetIsolate();
   17023          12 :   v8::HandleScope handle_scope(isolate);
   17024             : 
   17025             :   Local<v8::SharedArrayBuffer> ab =
   17026           6 :       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   17027             :   Local<v8::DataView> dv =
   17028           6 :       v8::DataView::New(ab, 2, kSize);
   17029           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   17030           6 :   CHECK_EQ(2u, dv->ByteOffset());
   17031           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   17032          24 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   17033           6 : }
   17034             : 
   17035             : #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                     \
   17036             :   THREADED_TEST(Is##View) {                                                 \
   17037             :     LocalContext env;                                                       \
   17038             :     v8::Isolate* isolate = env->GetIsolate();                               \
   17039             :     v8::HandleScope handle_scope(isolate);                                  \
   17040             :                                                                             \
   17041             :     Local<Value> result = CompileRun(                                       \
   17042             :         "var ab = new ArrayBuffer(128);"                                    \
   17043             :         "new " #View "(ab)");                                               \
   17044             :     CHECK(result->IsArrayBufferView());                                     \
   17045             :     CHECK(result->Is##View());                                              \
   17046             :     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
   17047             :   }
   17048             : 
   17049       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   17050       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   17051       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   17052       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   17053       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   17054       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   17055       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   17056       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   17057       28367 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   17058       28367 : IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   17059             : 
   17060             : #undef IS_ARRAY_BUFFER_VIEW_TEST
   17061             : 
   17062             : 
   17063             : 
   17064       28343 : THREADED_TEST(ScriptContextDependence) {
   17065           6 :   LocalContext c1;
   17066          12 :   v8::HandleScope scope(c1->GetIsolate());
   17067             :   const char *source = "foo";
   17068             :   v8::Local<v8::Script> dep = v8_compile(source);
   17069             :   v8::ScriptCompiler::Source script_source(
   17070             :       v8::String::NewFromUtf8(c1->GetIsolate(), source,
   17071           6 :                               v8::NewStringType::kNormal)
   17072           6 :           .ToLocalChecked());
   17073             :   v8::Local<v8::UnboundScript> indep =
   17074           6 :       v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
   17075           6 :           .ToLocalChecked();
   17076             :   c1->Global()
   17077             :       ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
   17078           6 :                                                 v8::NewStringType::kNormal)
   17079             :                             .ToLocalChecked(),
   17080          30 :             v8::Integer::New(c1->GetIsolate(), 100))
   17081          12 :       .FromJust();
   17082          18 :   CHECK_EQ(
   17083             :       dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
   17084             :       100);
   17085          24 :   CHECK_EQ(indep->BindToCurrentContext()
   17086             :                ->Run(c1.local())
   17087             :                .ToLocalChecked()
   17088             :                ->Int32Value(c1.local())
   17089             :                .FromJust(),
   17090             :            100);
   17091          12 :   LocalContext c2;
   17092             :   c2->Global()
   17093             :       ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
   17094           6 :                                                 v8::NewStringType::kNormal)
   17095             :                             .ToLocalChecked(),
   17096          30 :             v8::Integer::New(c2->GetIsolate(), 101))
   17097          12 :       .FromJust();
   17098          18 :   CHECK_EQ(
   17099             :       dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
   17100             :       100);
   17101          24 :   CHECK_EQ(indep->BindToCurrentContext()
   17102             :                ->Run(c2.local())
   17103             :                .ToLocalChecked()
   17104             :                ->Int32Value(c2.local())
   17105             :                .FromJust(),
   17106           6 :            101);
   17107           6 : }
   17108             : 
   17109             : 
   17110       28343 : THREADED_TEST(StackTrace) {
   17111           6 :   LocalContext context;
   17112          12 :   v8::HandleScope scope(context->GetIsolate());
   17113          12 :   v8::TryCatch try_catch(context->GetIsolate());
   17114             :   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   17115           6 :   v8::Local<v8::String> src = v8_str(source);
   17116           6 :   v8::Local<v8::String> origin = v8_str("stack-trace-test");
   17117             :   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   17118          30 :   CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
   17119             :                                                  &script_source)
   17120             :             .ToLocalChecked()
   17121             :             ->BindToCurrentContext()
   17122             :             ->Run(context.local())
   17123             :             .IsEmpty());
   17124           6 :   CHECK(try_catch.HasCaught());
   17125             :   v8::String::Utf8Value stack(
   17126             :       context->GetIsolate(),
   17127          18 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   17128          18 :   CHECK_NOT_NULL(strstr(*stack, "at foo (stack-trace-test"));
   17129           6 : }
   17130             : 
   17131             : 
   17132             : // Checks that a StackFrame has certain expected values.
   17133         100 : void checkStackFrame(const char* expected_script_name,
   17134             :                      const char* expected_func_name, int expected_line_number,
   17135             :                      int expected_column, bool is_eval, bool is_constructor,
   17136             :                      v8::Local<v8::StackFrame> frame) {
   17137         100 :   v8::HandleScope scope(CcTest::isolate());
   17138         300 :   v8::String::Utf8Value func_name(CcTest::isolate(), frame->GetFunctionName());
   17139         300 :   v8::String::Utf8Value script_name(CcTest::isolate(), frame->GetScriptName());
   17140         100 :   if (*script_name == nullptr) {
   17141             :     // The situation where there is no associated script, like for evals.
   17142          35 :     CHECK_NULL(expected_script_name);
   17143             :   } else {
   17144          65 :     CHECK_NOT_NULL(strstr(*script_name, expected_script_name));
   17145             :   }
   17146         200 :   CHECK_NOT_NULL(strstr(*func_name, expected_func_name));
   17147         100 :   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   17148         100 :   CHECK_EQ(expected_column, frame->GetColumn());
   17149         100 :   CHECK_EQ(is_eval, frame->IsEval());
   17150         200 :   CHECK_EQ(is_constructor, frame->IsConstructor());
   17151         100 : }
   17152             : 
   17153             : 
   17154         180 : void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   17155          35 :   v8::HandleScope scope(args.GetIsolate());
   17156             :   const char* origin = "capture-stack-trace-test";
   17157             :   const int kOverviewTest = 1;
   17158             :   const int kDetailedTest = 2;
   17159             :   const int kFunctionName = 3;
   17160             :   const int kDisplayName = 4;
   17161             :   const int kFunctionNameAndDisplayName = 5;
   17162             :   const int kDisplayNameIsNotString = 6;
   17163             :   const int kFunctionNameIsNotString = 7;
   17164             : 
   17165          35 :   CHECK_EQ(args.Length(), 1);
   17166             : 
   17167          35 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   17168             :   v8::Isolate* isolate = args.GetIsolate();
   17169          70 :   int testGroup = args[0]->Int32Value(context).FromJust();
   17170          35 :   if (testGroup == kOverviewTest) {
   17171             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17172           5 :         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   17173           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   17174             :     checkStackFrame(origin, "bar", 2, 10, false, false,
   17175           5 :                     stackTrace->GetFrame(args.GetIsolate(), 0));
   17176             :     checkStackFrame(origin, "foo", 6, 3, false, true,
   17177           5 :                     stackTrace->GetFrame(isolate, 1));
   17178             :     // This is the source string inside the eval which has the call to foo.
   17179             :     checkStackFrame(nullptr, "", 1, 1, true, false,
   17180           5 :                     stackTrace->GetFrame(isolate, 2));
   17181             :     // The last frame is an anonymous function which has the initial eval call.
   17182             :     checkStackFrame(origin, "", 8, 7, false, false,
   17183           5 :                     stackTrace->GetFrame(isolate, 3));
   17184          30 :   } else if (testGroup == kDetailedTest) {
   17185             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17186           5 :         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17187           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   17188             :     checkStackFrame(origin, "bat", 4, 22, false, false,
   17189           5 :                     stackTrace->GetFrame(isolate, 0));
   17190             :     checkStackFrame(origin, "baz", 8, 3, false, true,
   17191           5 :                     stackTrace->GetFrame(isolate, 1));
   17192             :     bool is_eval = true;
   17193             :     // This is the source string inside the eval which has the call to baz.
   17194             :     checkStackFrame(nullptr, "", 1, 1, is_eval, false,
   17195           5 :                     stackTrace->GetFrame(isolate, 2));
   17196             :     // The last frame is an anonymous function which has the initial eval call.
   17197             :     checkStackFrame(origin, "", 10, 1, false, false,
   17198           5 :                     stackTrace->GetFrame(isolate, 3));
   17199          25 :   } else if (testGroup == kFunctionName) {
   17200             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17201           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17202           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17203             :     checkStackFrame(nullptr, "function.name", 3, 1, true, false,
   17204           5 :                     stackTrace->GetFrame(isolate, 0));
   17205          20 :   } else if (testGroup == kDisplayName) {
   17206             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17207           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17208           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17209             :     checkStackFrame(nullptr, "function.displayName", 3, 1, true, false,
   17210           5 :                     stackTrace->GetFrame(isolate, 0));
   17211          15 :   } else if (testGroup == kFunctionNameAndDisplayName) {
   17212             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17213           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17214           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17215             :     checkStackFrame(nullptr, "function.displayName", 3, 1, true, false,
   17216           5 :                     stackTrace->GetFrame(isolate, 0));
   17217          10 :   } else if (testGroup == kDisplayNameIsNotString) {
   17218             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17219           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17220           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17221             :     checkStackFrame(nullptr, "function.name", 3, 1, true, false,
   17222           5 :                     stackTrace->GetFrame(isolate, 0));
   17223           5 :   } else if (testGroup == kFunctionNameIsNotString) {
   17224             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17225           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   17226           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   17227             :     checkStackFrame(nullptr, "", 3, 1, true, false,
   17228           5 :                     stackTrace->GetFrame(isolate, 0));
   17229          35 :   }
   17230          35 : }
   17231             : 
   17232             : 
   17233             : // Tests the C++ StackTrace API.
   17234             : // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   17235             : // THREADED_TEST(CaptureStackTrace) {
   17236       28342 : TEST(CaptureStackTrace) {
   17237           5 :   v8::Isolate* isolate = CcTest::isolate();
   17238           5 :   v8::HandleScope scope(isolate);
   17239           5 :   v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
   17240           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17241             :   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   17242          15 :              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   17243          10 :   LocalContext context(nullptr, templ);
   17244             : 
   17245             :   // Test getting OVERVIEW information. Should ignore information that is not
   17246             :   // script name, function name, line number, and column offset.
   17247             :   const char *overview_source =
   17248             :     "function bar() {\n"
   17249             :     "  var y; AnalyzeStackInNativeCode(1);\n"
   17250             :     "}\n"
   17251             :     "function foo() {\n"
   17252             :     "\n"
   17253             :     "  bar();\n"
   17254             :     "}\n"
   17255             :     "var x;eval('new foo();');";
   17256           5 :   v8::Local<v8::String> overview_src = v8_str(overview_source);
   17257             :   v8::ScriptCompiler::Source script_source(overview_src,
   17258             :                                            v8::ScriptOrigin(origin));
   17259             :   v8::Local<Value> overview_result(
   17260             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
   17261           5 :           .ToLocalChecked()
   17262             :           ->BindToCurrentContext()
   17263          15 :           ->Run(context.local())
   17264           5 :           .ToLocalChecked());
   17265           5 :   CHECK(!overview_result.IsEmpty());
   17266           5 :   CHECK(overview_result->IsObject());
   17267             : 
   17268             :   // Test getting DETAILED information.
   17269             :   const char *detailed_source =
   17270             :     "function bat() {AnalyzeStackInNativeCode(2);\n"
   17271             :     "}\n"
   17272             :     "\n"
   17273             :     "function baz() {\n"
   17274             :     "  bat();\n"
   17275             :     "}\n"
   17276             :     "eval('new baz();');";
   17277           5 :   v8::Local<v8::String> detailed_src = v8_str(detailed_source);
   17278             :   // Make the script using a non-zero line and column offset.
   17279           5 :   v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   17280           5 :   v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   17281             :   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   17282             :   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   17283             :   v8::Local<v8::UnboundScript> detailed_script(
   17284             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
   17285           5 :           .ToLocalChecked());
   17286             :   v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
   17287          10 :                                        ->Run(context.local())
   17288           5 :                                        .ToLocalChecked());
   17289           5 :   CHECK(!detailed_result.IsEmpty());
   17290           5 :   CHECK(detailed_result->IsObject());
   17291             : 
   17292             :   // Test using function.name and function.displayName in stack trace
   17293             :   const char* function_name_source =
   17294             :       "function bar(function_name, display_name, testGroup) {\n"
   17295             :       "  var f = new Function(`AnalyzeStackInNativeCode(${testGroup});`);\n"
   17296             :       "  if (function_name) {\n"
   17297             :       "    Object.defineProperty(f, 'name', { value: function_name });\n"
   17298             :       "  }\n"
   17299             :       "  if (display_name) {\n"
   17300             :       "    f.displayName = display_name;"
   17301             :       "  }\n"
   17302             :       "  f()\n"
   17303             :       "}\n"
   17304             :       "bar('function.name', undefined, 3);\n"
   17305             :       "bar(undefined, 'function.displayName', 4);\n"
   17306             :       "bar('function.name', 'function.displayName', 5);\n"
   17307             :       "bar('function.name', 239, 6);\n"
   17308             :       "bar(239, undefined, 7);\n";
   17309             :   v8::Local<v8::String> function_name_src =
   17310             :       v8::String::NewFromUtf8(isolate, function_name_source,
   17311             :                               v8::NewStringType::kNormal)
   17312           5 :           .ToLocalChecked();
   17313             :   v8::ScriptCompiler::Source script_source3(function_name_src,
   17314             :                                             v8::ScriptOrigin(origin));
   17315             :   v8::Local<Value> function_name_result(
   17316             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
   17317           5 :           .ToLocalChecked()
   17318             :           ->BindToCurrentContext()
   17319          15 :           ->Run(context.local())
   17320           5 :           .ToLocalChecked());
   17321          10 :   CHECK(!function_name_result.IsEmpty());
   17322           5 : }
   17323             : 
   17324             : 
   17325           5 : static void StackTraceForUncaughtExceptionListener(
   17326             :     v8::Local<v8::Message> message, v8::Local<Value>) {
   17327           5 :   report_count++;
   17328           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17329           5 :   CHECK_EQ(2, stack_trace->GetFrameCount());
   17330             :   checkStackFrame("origin", "foo", 2, 3, false, false,
   17331           5 :                   stack_trace->GetFrame(message->GetIsolate(), 0));
   17332             :   checkStackFrame("origin", "bar", 5, 3, false, false,
   17333           5 :                   stack_trace->GetFrame(message->GetIsolate(), 1));
   17334           5 : }
   17335             : 
   17336             : 
   17337       28342 : TEST(CaptureStackTraceForUncaughtException) {
   17338           5 :   report_count = 0;
   17339           5 :   LocalContext env;
   17340           5 :   v8::Isolate* isolate = env->GetIsolate();
   17341          10 :   v8::HandleScope scope(isolate);
   17342           5 :   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   17343           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17344             : 
   17345             :   CompileRunWithOrigin(
   17346             :       "function foo() {\n"
   17347             :       "  throw 1;\n"
   17348             :       "};\n"
   17349             :       "function bar() {\n"
   17350             :       "  foo();\n"
   17351             :       "};",
   17352             :       "origin");
   17353           5 :   v8::Local<v8::Object> global = env->Global();
   17354             :   Local<Value> trouble =
   17355          20 :       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   17356           5 :   CHECK(trouble->IsFunction());
   17357          10 :   CHECK(Function::Cast(*trouble)
   17358             :             ->Call(env.local(), global, 0, nullptr)
   17359             :             .IsEmpty());
   17360           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17361           5 :   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   17362          10 :   CHECK_EQ(1, report_count);
   17363           5 : }
   17364             : 
   17365       28342 : TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   17366           5 :   LocalContext env;
   17367           5 :   v8::Isolate* isolate = env->GetIsolate();
   17368          10 :   v8::HandleScope scope(isolate);
   17369             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
   17370           5 :                                                      v8::StackTrace::kDetailed);
   17371             : 
   17372             :   CompileRun(
   17373             :       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   17374             :       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   17375             :       "    'isConstructor'];\n"
   17376             :       "for (var i = 0; i < setters.length; i++) {\n"
   17377             :       "  var prop = setters[i];\n"
   17378             :       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   17379             :       "}\n");
   17380             :   CompileRun("throw 'exception';");
   17381          10 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17382           5 : }
   17383             : 
   17384             : static int asm_warning_triggered = 0;
   17385             : 
   17386           5 : static void AsmJsWarningListener(v8::Local<v8::Message> message,
   17387             :                                  v8::Local<Value>) {
   17388             :   DCHECK_EQ(v8::Isolate::kMessageWarning, message->ErrorLevel());
   17389           5 :   asm_warning_triggered = 1;
   17390           5 : }
   17391             : 
   17392       28342 : TEST(AsmJsWarning) {
   17393           5 :   i::FLAG_validate_asm = true;
   17394           5 :   if (i::FLAG_suppress_asm_messages) return;
   17395             : 
   17396           5 :   LocalContext env;
   17397           5 :   v8::Isolate* isolate = env->GetIsolate();
   17398          10 :   v8::HandleScope scope(isolate);
   17399             : 
   17400           5 :   asm_warning_triggered = 0;
   17401             :   isolate->AddMessageListenerWithErrorLevel(AsmJsWarningListener,
   17402           5 :                                             v8::Isolate::kMessageAll);
   17403             :   CompileRun(
   17404             :       "function module() {\n"
   17405             :       "  'use asm';\n"
   17406             :       "  var x = 'hi';\n"
   17407             :       "  return {};\n"
   17408             :       "}\n"
   17409             :       "module();");
   17410             :   DCHECK_EQ(1, asm_warning_triggered);
   17411          10 :   isolate->RemoveMessageListeners(AsmJsWarningListener);
   17412             : }
   17413             : 
   17414             : static int error_level_message_count = 0;
   17415             : static int expected_error_level = 0;
   17416             : 
   17417          20 : static void ErrorLevelListener(v8::Local<v8::Message> message,
   17418             :                                v8::Local<Value>) {
   17419             :   DCHECK_EQ(expected_error_level, message->ErrorLevel());
   17420          20 :   ++error_level_message_count;
   17421          20 : }
   17422             : 
   17423       28342 : TEST(ErrorLevelWarning) {
   17424           5 :   LocalContext env;
   17425           5 :   v8::Isolate* isolate = env->GetIsolate();
   17426             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   17427          10 :   v8::HandleScope scope(isolate);
   17428             : 
   17429             :   const char* source = "fake = 1;";
   17430           5 :   v8::Local<v8::Script> lscript = CompileWithOrigin(source, "test");
   17431             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   17432          10 :       v8::Utils::OpenHandle(*lscript->GetUnboundScript()));
   17433          10 :   CHECK(obj->script()->IsScript());
   17434          10 :   i::Handle<i::Script> script(i::Script::cast(obj->script()), i_isolate);
   17435             : 
   17436             :   int levels[] = {
   17437             :       v8::Isolate::kMessageLog, v8::Isolate::kMessageInfo,
   17438             :       v8::Isolate::kMessageDebug, v8::Isolate::kMessageWarning,
   17439           5 :   };
   17440           5 :   error_level_message_count = 0;
   17441             :   isolate->AddMessageListenerWithErrorLevel(ErrorLevelListener,
   17442           5 :                                             v8::Isolate::kMessageAll);
   17443          25 :   for (size_t i = 0; i < arraysize(levels); i++) {
   17444          20 :     i::MessageLocation location(script, 0, 0);
   17445             :     i::Handle<i::String> msg(i_isolate->factory()->InternalizeOneByteString(
   17446          20 :         i::StaticCharVector("test")));
   17447             :     i::Handle<i::JSMessageObject> message =
   17448             :         i::MessageHandler::MakeMessageObject(
   17449             :             i_isolate, i::MessageTemplate::kAsmJsInvalid, &location, msg,
   17450          20 :             i::Handle<i::FixedArray>::null());
   17451          20 :     message->set_error_level(levels[i]);
   17452          20 :     expected_error_level = levels[i];
   17453          20 :     i::MessageHandler::ReportMessage(i_isolate, &location, message);
   17454             :   }
   17455           5 :   isolate->RemoveMessageListeners(ErrorLevelListener);
   17456           5 :   DCHECK_EQ(arraysize(levels), error_level_message_count);
   17457           5 : }
   17458             : 
   17459           5 : static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
   17460             :                                            v8::Local<Value>) {
   17461           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17462           5 :   v8::Isolate* isolate = message->GetIsolate();
   17463           5 :   CHECK_EQ(5, stack_trace->GetFrameCount());
   17464             :   checkStackFrame("origin", "foo:0", 4, 7, false, false,
   17465           5 :                   stack_trace->GetFrame(isolate, 0));
   17466             :   checkStackFrame("origin", "foo:1", 5, 27, false, false,
   17467           5 :                   stack_trace->GetFrame(isolate, 1));
   17468             :   checkStackFrame("origin", "foo", 5, 27, false, false,
   17469           5 :                   stack_trace->GetFrame(isolate, 2));
   17470             :   checkStackFrame("origin", "foo", 5, 27, false, false,
   17471           5 :                   stack_trace->GetFrame(isolate, 3));
   17472             :   checkStackFrame("origin", "", 1, 14, false, false,
   17473           5 :                   stack_trace->GetFrame(isolate, 4));
   17474           5 : }
   17475             : 
   17476             : 
   17477       28342 : TEST(GetStackTraceContainsFunctionsWithFunctionName) {
   17478           5 :   LocalContext env;
   17479           5 :   v8::Isolate* isolate = env->GetIsolate();
   17480          10 :   v8::HandleScope scope(isolate);
   17481             : 
   17482             :   CompileRunWithOrigin(
   17483             :       "function gen(name, counter) {\n"
   17484             :       "  var f = function foo() {\n"
   17485             :       "    if (counter === 0)\n"
   17486             :       "      throw 1;\n"
   17487             :       "    gen(name, counter - 1)();\n"
   17488             :       "  };\n"
   17489             :       "  if (counter == 3) {\n"
   17490             :       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
   17491             :       "  } else {\n"
   17492             :       "    Object.defineProperty(f, 'name', {writable:true});\n"
   17493             :       "    if (counter == 2)\n"
   17494             :       "      f.name = 42;\n"
   17495             :       "    else\n"
   17496             :       "      f.name = name + ':' + counter;\n"
   17497             :       "  }\n"
   17498             :       "  return f;\n"
   17499             :       "};",
   17500             :       "origin");
   17501             : 
   17502           5 :   isolate->AddMessageListener(StackTraceFunctionNameListener);
   17503           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17504             :   CompileRunWithOrigin("gen('foo', 3)();", "origin");
   17505           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17506          10 :   isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
   17507           5 : }
   17508             : 
   17509             : 
   17510           5 : static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
   17511             :                                      v8::Local<v8::Value> data) {
   17512             :   // Use the frame where JavaScript is called from.
   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(3, frame_count);
   17517           5 :   int line_number[] = {1, 2, 5};
   17518          20 :   for (int i = 0; i < frame_count; i++) {
   17519          30 :     CHECK_EQ(line_number[i],
   17520             :              stack_trace->GetFrame(message->GetIsolate(), i)->GetLineNumber());
   17521             :   }
   17522           5 : }
   17523             : 
   17524             : 
   17525             : // Test that we only return the stack trace at the site where the exception
   17526             : // is first thrown (not where it is rethrown).
   17527       28342 : TEST(RethrowStackTrace) {
   17528           5 :   LocalContext env;
   17529           5 :   v8::Isolate* isolate = env->GetIsolate();
   17530          10 :   v8::HandleScope scope(isolate);
   17531             :   // We make sure that
   17532             :   // - the stack trace of the ReferenceError in g() is reported.
   17533             :   // - the stack trace is not overwritten when e1 is rethrown by t().
   17534             :   // - the stack trace of e2 does not overwrite that of e1.
   17535             :   const char* source =
   17536             :       "function g() { error; }          \n"
   17537             :       "function f() { g(); }            \n"
   17538             :       "function t(e) { throw e; }       \n"
   17539             :       "try {                            \n"
   17540             :       "  f();                           \n"
   17541             :       "} catch (e1) {                   \n"
   17542             :       "  try {                          \n"
   17543             :       "    error;                       \n"
   17544             :       "  } catch (e2) {                 \n"
   17545             :       "    t(e1);                       \n"
   17546             :       "  }                              \n"
   17547             :       "}                                \n";
   17548           5 :   isolate->AddMessageListener(RethrowStackTraceHandler);
   17549           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17550             :   CompileRun(source);
   17551           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17552          10 :   isolate->RemoveMessageListeners(RethrowStackTraceHandler);
   17553           5 : }
   17554             : 
   17555             : 
   17556           5 : static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
   17557             :                                               v8::Local<v8::Value> data) {
   17558           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17559           5 :   CHECK(!stack_trace.IsEmpty());
   17560           5 :   int frame_count = stack_trace->GetFrameCount();
   17561           5 :   CHECK_EQ(2, frame_count);
   17562           5 :   int line_number[] = {3, 7};
   17563          15 :   for (int i = 0; i < frame_count; i++) {
   17564          20 :     CHECK_EQ(line_number[i],
   17565             :              stack_trace->GetFrame(message->GetIsolate(), i)->GetLineNumber());
   17566             :   }
   17567           5 : }
   17568             : 
   17569             : 
   17570             : // Test that we do not recognize identity for primitive exceptions.
   17571       28342 : TEST(RethrowPrimitiveStackTrace) {
   17572           5 :   LocalContext env;
   17573           5 :   v8::Isolate* isolate = env->GetIsolate();
   17574          10 :   v8::HandleScope scope(isolate);
   17575             :   // We do not capture stack trace for non Error objects on creation time.
   17576             :   // Instead, we capture the stack trace on last throw.
   17577             :   const char* source =
   17578             :       "function g() { throw 404; }      \n"
   17579             :       "function f() { g(); }            \n"
   17580             :       "function t(e) { throw e; }       \n"
   17581             :       "try {                            \n"
   17582             :       "  f();                           \n"
   17583             :       "} catch (e1) {                   \n"
   17584             :       "  t(e1)                          \n"
   17585             :       "}                                \n";
   17586           5 :   isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
   17587           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17588             :   CompileRun(source);
   17589           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17590          10 :   isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   17591           5 : }
   17592             : 
   17593             : 
   17594           5 : static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
   17595             :                                              v8::Local<v8::Value> data) {
   17596             :   // Use the frame where JavaScript is called from.
   17597           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17598           5 :   CHECK(!stack_trace.IsEmpty());
   17599           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   17600          10 :   CHECK_EQ(1, stack_trace->GetFrame(message->GetIsolate(), 0)->GetLineNumber());
   17601           5 : }
   17602             : 
   17603             : 
   17604             : // Test that the stack trace is captured when the error object is created and
   17605             : // not where it is thrown.
   17606       28342 : TEST(RethrowExistingStackTrace) {
   17607           5 :   LocalContext env;
   17608           5 :   v8::Isolate* isolate = env->GetIsolate();
   17609          10 :   v8::HandleScope scope(isolate);
   17610             :   const char* source =
   17611             :       "var e = new Error();           \n"
   17612             :       "throw e;                       \n";
   17613           5 :   isolate->AddMessageListener(RethrowExistingStackTraceHandler);
   17614           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17615             :   CompileRun(source);
   17616           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17617          10 :   isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
   17618           5 : }
   17619             : 
   17620             : 
   17621           5 : static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
   17622             :                                                v8::Local<v8::Value> data) {
   17623             :   // Use the frame where JavaScript is called from.
   17624           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17625           5 :   CHECK(!stack_trace.IsEmpty());
   17626           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   17627          10 :   CHECK_EQ(2, stack_trace->GetFrame(message->GetIsolate(), 0)->GetLineNumber());
   17628           5 : }
   17629             : 
   17630             : 
   17631             : // Test that the stack trace is captured where the bogus Error object is thrown.
   17632       28342 : TEST(RethrowBogusErrorStackTrace) {
   17633           5 :   LocalContext env;
   17634           5 :   v8::Isolate* isolate = env->GetIsolate();
   17635          10 :   v8::HandleScope scope(isolate);
   17636             :   const char* source =
   17637             :       "var e = {__proto__: new Error()} \n"
   17638             :       "throw e;                         \n";
   17639           5 :   isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
   17640           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17641             :   CompileRun(source);
   17642           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17643          10 :   isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   17644           5 : }
   17645             : 
   17646             : 
   17647             : v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
   17648             : int promise_reject_counter = 0;
   17649             : int promise_revoke_counter = 0;
   17650             : int promise_reject_after_resolved_counter = 0;
   17651             : int promise_resolve_after_resolved_counter = 0;
   17652             : int promise_reject_msg_line_number = -1;
   17653             : int promise_reject_msg_column_number = -1;
   17654             : int promise_reject_line_number = -1;
   17655             : int promise_reject_column_number = -1;
   17656             : int promise_reject_frame_count = -1;
   17657             : bool promise_reject_is_shared_cross_origin = false;
   17658             : 
   17659         140 : void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
   17660         140 :   v8::Local<v8::Object> global = CcTest::global();
   17661         140 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17662         140 :   CHECK_NE(v8::Promise::PromiseState::kPending,
   17663             :            reject_message.GetPromise()->State());
   17664         140 :   switch (reject_message.GetEvent()) {
   17665             :     case v8::kPromiseRejectWithNoHandler: {
   17666          95 :       promise_reject_counter++;
   17667         190 :       global->Set(context, v8_str("rejected"), reject_message.GetPromise())
   17668         190 :           .FromJust();
   17669         190 :       global->Set(context, v8_str("value"), reject_message.GetValue())
   17670         190 :           .FromJust();
   17671             :       v8::Local<v8::Message> message = v8::Exception::CreateMessage(
   17672          95 :           CcTest::isolate(), reject_message.GetValue());
   17673          95 :       v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17674             : 
   17675             :       promise_reject_msg_line_number =
   17676         190 :           message->GetLineNumber(context).FromJust();
   17677             :       promise_reject_msg_column_number =
   17678         190 :           message->GetStartColumn(context).FromJust() + 1;
   17679             :       promise_reject_is_shared_cross_origin =
   17680          95 :           message->IsSharedCrossOrigin();
   17681             : 
   17682          95 :       if (!stack_trace.IsEmpty()) {
   17683          35 :         promise_reject_frame_count = stack_trace->GetFrameCount();
   17684          35 :         if (promise_reject_frame_count > 0) {
   17685         150 :           CHECK(stack_trace->GetFrame(CcTest::isolate(), 0)
   17686             :                     ->GetScriptName()
   17687             :                     ->Equals(context, v8_str("pro"))
   17688             :                     .FromJust());
   17689             :           promise_reject_line_number =
   17690          60 :               stack_trace->GetFrame(CcTest::isolate(), 0)->GetLineNumber();
   17691             :           promise_reject_column_number =
   17692          60 :               stack_trace->GetFrame(CcTest::isolate(), 0)->GetColumn();
   17693             :         } else {
   17694           5 :           promise_reject_line_number = -1;
   17695           5 :           promise_reject_column_number = -1;
   17696             :         }
   17697             :       }
   17698             :       break;
   17699             :     }
   17700             :     case v8::kPromiseHandlerAddedAfterReject: {
   17701          30 :       promise_revoke_counter++;
   17702          60 :       global->Set(context, v8_str("revoked"), reject_message.GetPromise())
   17703          60 :           .FromJust();
   17704          30 :       CHECK(reject_message.GetValue().IsEmpty());
   17705             :       break;
   17706             :     }
   17707             :     case v8::kPromiseRejectAfterResolved: {
   17708          10 :       promise_reject_after_resolved_counter++;
   17709          10 :       break;
   17710             :     }
   17711             :     case v8::kPromiseResolveAfterResolved: {
   17712           5 :       promise_resolve_after_resolved_counter++;
   17713           5 :       break;
   17714             :     }
   17715             :   }
   17716         140 : }
   17717             : 
   17718             : 
   17719         600 : v8::Local<v8::Promise> GetPromise(const char* name) {
   17720             :   return v8::Local<v8::Promise>::Cast(
   17721             :       CcTest::global()
   17722        1800 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   17723        1200 :           .ToLocalChecked());
   17724             : }
   17725             : 
   17726             : 
   17727          35 : v8::Local<v8::Value> RejectValue() {
   17728             :   return CcTest::global()
   17729         105 :       ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17730          70 :       .ToLocalChecked();
   17731             : }
   17732             : 
   17733             : 
   17734          70 : void ResetPromiseStates() {
   17735          70 :   promise_reject_counter = 0;
   17736          70 :   promise_revoke_counter = 0;
   17737          70 :   promise_reject_after_resolved_counter = 0;
   17738          70 :   promise_resolve_after_resolved_counter = 0;
   17739          70 :   promise_reject_msg_line_number = -1;
   17740          70 :   promise_reject_msg_column_number = -1;
   17741          70 :   promise_reject_line_number = -1;
   17742          70 :   promise_reject_column_number = -1;
   17743          70 :   promise_reject_frame_count = -1;
   17744             : 
   17745          70 :   v8::Local<v8::Object> global = CcTest::global();
   17746          70 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17747         280 :   global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
   17748         280 :   global->Set(context, v8_str("value"), v8_str("")).FromJust();
   17749         280 :   global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
   17750          70 : }
   17751             : 
   17752             : 
   17753       28342 : TEST(PromiseRejectCallback) {
   17754           5 :   LocalContext env;
   17755           5 :   v8::Isolate* isolate = env->GetIsolate();
   17756          10 :   v8::HandleScope scope(isolate);
   17757             : 
   17758           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17759             : 
   17760           5 :   ResetPromiseStates();
   17761             : 
   17762             :   // Create promise p0.
   17763             :   CompileRun(
   17764             :       "var reject;            \n"
   17765             :       "var p0 = new Promise(  \n"
   17766             :       "  function(res, rej) { \n"
   17767             :       "    reject = rej;      \n"
   17768             :       "  }                    \n"
   17769             :       ");                     \n");
   17770          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17771           5 :   CHECK_EQ(0, promise_reject_counter);
   17772           5 :   CHECK_EQ(0, promise_revoke_counter);
   17773             : 
   17774             :   // Add resolve handler (and default reject handler) to p0.
   17775             :   CompileRun("var p1 = p0.then(function(){});");
   17776          10 :   CHECK(GetPromise("p0")->HasHandler());
   17777          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17778           5 :   CHECK_EQ(0, promise_reject_counter);
   17779           5 :   CHECK_EQ(0, promise_revoke_counter);
   17780             : 
   17781             :   // Reject p0.
   17782             :   CompileRun("reject('ppp');");
   17783          10 :   CHECK(GetPromise("p0")->HasHandler());
   17784          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17785           5 :   CHECK_EQ(1, promise_reject_counter);
   17786           5 :   CHECK_EQ(0, promise_revoke_counter);
   17787           5 :   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
   17788          20 :   CHECK(
   17789             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
   17790          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17791             : 
   17792             :   // Reject p0 again. Callback is not triggered again.
   17793             :   CompileRun("reject();");
   17794          10 :   CHECK(GetPromise("p0")->HasHandler());
   17795          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17796           5 :   CHECK_EQ(1, promise_reject_counter);
   17797           5 :   CHECK_EQ(0, promise_revoke_counter);
   17798             : 
   17799             :   // Add resolve handler to p1.
   17800             :   CompileRun("var p2 = p1.then(function(){});");
   17801          10 :   CHECK(GetPromise("p0")->HasHandler());
   17802          10 :   CHECK(GetPromise("p1")->HasHandler());
   17803          10 :   CHECK(!GetPromise("p2")->HasHandler());
   17804           5 :   CHECK_EQ(2, promise_reject_counter);
   17805           5 :   CHECK_EQ(1, promise_revoke_counter);
   17806          20 :   CHECK(
   17807             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
   17808          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17809          20 :   CHECK(
   17810             :       GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
   17811             : 
   17812           5 :   ResetPromiseStates();
   17813             : 
   17814             :   // Create promise q0.
   17815             :   CompileRun(
   17816             :       "var q0 = new Promise(  \n"
   17817             :       "  function(res, rej) { \n"
   17818             :       "    reject = rej;      \n"
   17819             :       "  }                    \n"
   17820             :       ");                     \n");
   17821          10 :   CHECK(!GetPromise("q0")->HasHandler());
   17822           5 :   CHECK_EQ(0, promise_reject_counter);
   17823           5 :   CHECK_EQ(0, promise_revoke_counter);
   17824             : 
   17825             :   // Add reject handler to q0.
   17826             :   CompileRun("var q1 = q0.catch(function() {});");
   17827          10 :   CHECK(GetPromise("q0")->HasHandler());
   17828          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17829           5 :   CHECK_EQ(0, promise_reject_counter);
   17830           5 :   CHECK_EQ(0, promise_revoke_counter);
   17831             : 
   17832             :   // Reject q0.
   17833             :   CompileRun("reject('qq')");
   17834          10 :   CHECK(GetPromise("q0")->HasHandler());
   17835          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17836           5 :   CHECK_EQ(0, promise_reject_counter);
   17837           5 :   CHECK_EQ(0, promise_revoke_counter);
   17838             : 
   17839             :   // Add a new reject handler, which rejects by returning Promise.reject().
   17840             :   // The returned promise q_ triggers a reject callback at first, only to
   17841             :   // revoke it when returning it causes q2 to be rejected.
   17842             :   CompileRun(
   17843             :       "var q_;"
   17844             :       "var q2 = q0.catch(               \n"
   17845             :       "   function() {                  \n"
   17846             :       "     q_ = Promise.reject('qqq'); \n"
   17847             :       "     return q_;                  \n"
   17848             :       "   }                             \n"
   17849             :       ");                               \n");
   17850          10 :   CHECK(GetPromise("q0")->HasHandler());
   17851          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17852          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17853          10 :   CHECK(GetPromise("q_")->HasHandler());
   17854           5 :   CHECK_EQ(2, promise_reject_counter);
   17855           5 :   CHECK_EQ(1, promise_revoke_counter);
   17856          20 :   CHECK(
   17857             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
   17858          20 :   CHECK(
   17859             :       GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
   17860          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
   17861             : 
   17862             :   // Add a reject handler to the resolved q1, which rejects by throwing.
   17863             :   CompileRun(
   17864             :       "var q3 = q1.then(  \n"
   17865             :       "   function() {    \n"
   17866             :       "     throw 'qqqq'; \n"
   17867             :       "   }               \n"
   17868             :       ");                 \n");
   17869          10 :   CHECK(GetPromise("q0")->HasHandler());
   17870          10 :   CHECK(GetPromise("q1")->HasHandler());
   17871          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17872          10 :   CHECK(!GetPromise("q3")->HasHandler());
   17873           5 :   CHECK_EQ(3, promise_reject_counter);
   17874           5 :   CHECK_EQ(1, promise_revoke_counter);
   17875          20 :   CHECK(
   17876             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
   17877          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
   17878             : 
   17879           5 :   ResetPromiseStates();
   17880             : 
   17881             :   // Create promise r0, which has three handlers, two of which handle rejects.
   17882             :   CompileRun(
   17883             :       "var r0 = new Promise(             \n"
   17884             :       "  function(res, rej) {            \n"
   17885             :       "    reject = rej;                 \n"
   17886             :       "  }                               \n"
   17887             :       ");                                \n"
   17888             :       "var r1 = r0.catch(function() {}); \n"
   17889             :       "var r2 = r0.then(function() {});  \n"
   17890             :       "var r3 = r0.then(function() {},   \n"
   17891             :       "                 function() {});  \n");
   17892          10 :   CHECK(GetPromise("r0")->HasHandler());
   17893          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17894          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17895          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17896           5 :   CHECK_EQ(0, promise_reject_counter);
   17897           5 :   CHECK_EQ(0, promise_revoke_counter);
   17898             : 
   17899             :   // Reject r0.
   17900             :   CompileRun("reject('rrr')");
   17901          10 :   CHECK(GetPromise("r0")->HasHandler());
   17902          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17903          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17904          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17905           5 :   CHECK_EQ(1, promise_reject_counter);
   17906           5 :   CHECK_EQ(0, promise_revoke_counter);
   17907          20 :   CHECK(
   17908             :       GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
   17909          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17910             : 
   17911             :   // Add reject handler to r2.
   17912             :   CompileRun("var r4 = r2.catch(function() {});");
   17913          10 :   CHECK(GetPromise("r0")->HasHandler());
   17914          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17915          10 :   CHECK(GetPromise("r2")->HasHandler());
   17916          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17917          10 :   CHECK(!GetPromise("r4")->HasHandler());
   17918           5 :   CHECK_EQ(1, promise_reject_counter);
   17919           5 :   CHECK_EQ(1, promise_revoke_counter);
   17920          20 :   CHECK(
   17921             :       GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
   17922          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17923             : 
   17924             :   // Add reject handlers to r4.
   17925             :   CompileRun("var r5 = r4.then(function() {}, function() {});");
   17926          10 :   CHECK(GetPromise("r0")->HasHandler());
   17927          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17928          10 :   CHECK(GetPromise("r2")->HasHandler());
   17929          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17930          10 :   CHECK(GetPromise("r4")->HasHandler());
   17931          10 :   CHECK(!GetPromise("r5")->HasHandler());
   17932           5 :   CHECK_EQ(1, promise_reject_counter);
   17933           5 :   CHECK_EQ(1, promise_revoke_counter);
   17934             : 
   17935           5 :   ResetPromiseStates();
   17936             : 
   17937             :   // Create promise s0, which has three handlers, none of which handle rejects.
   17938             :   CompileRun(
   17939             :       "var s0 = new Promise(            \n"
   17940             :       "  function(res, rej) {           \n"
   17941             :       "    reject = rej;                \n"
   17942             :       "  }                              \n"
   17943             :       ");                               \n"
   17944             :       "var s1 = s0.then(function() {}); \n"
   17945             :       "var s2 = s0.then(function() {}); \n"
   17946             :       "var s3 = s0.then(function() {}); \n");
   17947          10 :   CHECK(GetPromise("s0")->HasHandler());
   17948          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17949          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17950          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17951           5 :   CHECK_EQ(0, promise_reject_counter);
   17952           5 :   CHECK_EQ(0, promise_revoke_counter);
   17953             : 
   17954             :   // Reject s0.
   17955             :   CompileRun("reject('sss')");
   17956          10 :   CHECK(GetPromise("s0")->HasHandler());
   17957          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17958          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17959          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17960           5 :   CHECK_EQ(3, promise_reject_counter);
   17961           5 :   CHECK_EQ(0, promise_revoke_counter);
   17962          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
   17963             : 
   17964           5 :   ResetPromiseStates();
   17965             : 
   17966             :   // Swallowed exceptions in the Promise constructor.
   17967             :   CompileRun(
   17968             :       "var v0 = new Promise(\n"
   17969             :       "  function(res, rej) {\n"
   17970             :       "    res(1);\n"
   17971             :       "    throw new Error();\n"
   17972             :       "  }\n"
   17973             :       ");\n");
   17974          10 :   CHECK(!GetPromise("v0")->HasHandler());
   17975           5 :   CHECK_EQ(0, promise_reject_counter);
   17976           5 :   CHECK_EQ(0, promise_revoke_counter);
   17977           5 :   CHECK_EQ(1, promise_reject_after_resolved_counter);
   17978           5 :   CHECK_EQ(0, promise_resolve_after_resolved_counter);
   17979             : 
   17980           5 :   ResetPromiseStates();
   17981             : 
   17982             :   // Duplication resolve.
   17983             :   CompileRun(
   17984             :       "var r;\n"
   17985             :       "var y0 = new Promise(\n"
   17986             :       "  function(res, rej) {\n"
   17987             :       "    r = res;\n"
   17988             :       "    throw new Error();\n"
   17989             :       "  }\n"
   17990             :       ");\n"
   17991             :       "r(1);\n");
   17992          10 :   CHECK(!GetPromise("y0")->HasHandler());
   17993           5 :   CHECK_EQ(1, promise_reject_counter);
   17994           5 :   CHECK_EQ(0, promise_revoke_counter);
   17995           5 :   CHECK_EQ(0, promise_reject_after_resolved_counter);
   17996           5 :   CHECK_EQ(1, promise_resolve_after_resolved_counter);
   17997             : 
   17998             :   // Test stack frames.
   17999           5 :   env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   18000             : 
   18001           5 :   ResetPromiseStates();
   18002             : 
   18003             :   // Create promise t0, which is rejected in the constructor with an error.
   18004             :   CompileRunWithOrigin(
   18005             :       "var t0 = new Promise(  \n"
   18006             :       "  function(res, rej) { \n"
   18007             :       "    reference_error;   \n"
   18008             :       "  }                    \n"
   18009             :       ");                     \n",
   18010           5 :       "pro", 0, 0);
   18011          10 :   CHECK(!GetPromise("t0")->HasHandler());
   18012           5 :   CHECK_EQ(1, promise_reject_counter);
   18013           5 :   CHECK_EQ(0, promise_revoke_counter);
   18014           5 :   CHECK_EQ(2, promise_reject_frame_count);
   18015           5 :   CHECK_EQ(3, promise_reject_line_number);
   18016           5 :   CHECK_EQ(5, promise_reject_column_number);
   18017           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   18018           5 :   CHECK_EQ(5, promise_reject_msg_column_number);
   18019             : 
   18020           5 :   ResetPromiseStates();
   18021             : 
   18022             :   // Create promise u0 and chain u1 to it, which is rejected via throw.
   18023             :   CompileRunWithOrigin(
   18024             :       "var u0 = Promise.resolve();        \n"
   18025             :       "var u1 = u0.then(                  \n"
   18026             :       "           function() {            \n"
   18027             :       "             (function() {         \n"
   18028             :       "                throw new Error(); \n"
   18029             :       "              })();                \n"
   18030             :       "           }                       \n"
   18031             :       "         );                        \n",
   18032           5 :       "pro", 0, 0);
   18033          10 :   CHECK(GetPromise("u0")->HasHandler());
   18034          10 :   CHECK(!GetPromise("u1")->HasHandler());
   18035           5 :   CHECK_EQ(1, promise_reject_counter);
   18036           5 :   CHECK_EQ(0, promise_revoke_counter);
   18037           5 :   CHECK_EQ(2, promise_reject_frame_count);
   18038           5 :   CHECK_EQ(5, promise_reject_line_number);
   18039           5 :   CHECK_EQ(23, promise_reject_column_number);
   18040           5 :   CHECK_EQ(5, promise_reject_msg_line_number);
   18041           5 :   CHECK_EQ(23, promise_reject_msg_column_number);
   18042             : 
   18043             :   // Throw in u3, which handles u1's rejection.
   18044             :   CompileRunWithOrigin(
   18045             :       "function f() {                \n"
   18046             :       "  return (function() {        \n"
   18047             :       "    return new Error();       \n"
   18048             :       "  })();                       \n"
   18049             :       "}                             \n"
   18050             :       "var u2 = Promise.reject(f()); \n"
   18051             :       "var u3 = u1.catch(            \n"
   18052             :       "           function() {       \n"
   18053             :       "             return u2;       \n"
   18054             :       "           }                  \n"
   18055             :       "         );                   \n",
   18056           5 :       "pro", 0, 0);
   18057          10 :   CHECK(GetPromise("u0")->HasHandler());
   18058          10 :   CHECK(GetPromise("u1")->HasHandler());
   18059          10 :   CHECK(GetPromise("u2")->HasHandler());
   18060          10 :   CHECK(!GetPromise("u3")->HasHandler());
   18061           5 :   CHECK_EQ(3, promise_reject_counter);
   18062           5 :   CHECK_EQ(2, promise_revoke_counter);
   18063           5 :   CHECK_EQ(3, promise_reject_frame_count);
   18064           5 :   CHECK_EQ(3, promise_reject_line_number);
   18065           5 :   CHECK_EQ(12, promise_reject_column_number);
   18066           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   18067           5 :   CHECK_EQ(12, promise_reject_msg_column_number);
   18068             : 
   18069           5 :   ResetPromiseStates();
   18070             : 
   18071             :   // Create promise rejected promise v0, which is incorrectly handled by v1
   18072             :   // via chaining cycle.
   18073             :   CompileRunWithOrigin(
   18074             :       "var v0 = Promise.reject(); \n"
   18075             :       "var v1 = v0.catch(         \n"
   18076             :       "           function() {    \n"
   18077             :       "             return v1;    \n"
   18078             :       "           }               \n"
   18079             :       "         );                \n",
   18080           5 :       "pro", 0, 0);
   18081          10 :   CHECK(GetPromise("v0")->HasHandler());
   18082          10 :   CHECK(!GetPromise("v1")->HasHandler());
   18083           5 :   CHECK_EQ(2, promise_reject_counter);
   18084           5 :   CHECK_EQ(1, promise_revoke_counter);
   18085           5 :   CHECK_EQ(0, promise_reject_frame_count);
   18086           5 :   CHECK_EQ(-1, promise_reject_line_number);
   18087           5 :   CHECK_EQ(-1, promise_reject_column_number);
   18088             : 
   18089           5 :   ResetPromiseStates();
   18090             : 
   18091             :   // Create promise t1, which rejects by throwing syntax error from eval.
   18092             :   CompileRunWithOrigin(
   18093             :       "var t1 = new Promise(   \n"
   18094             :       "  function(res, rej) {  \n"
   18095             :       "    var content = '\\n\\\n"
   18096             :       "      }';               \n"
   18097             :       "    eval(content);      \n"
   18098             :       "  }                     \n"
   18099             :       ");                      \n",
   18100           5 :       "pro", 0, 0);
   18101          10 :   CHECK(!GetPromise("t1")->HasHandler());
   18102           5 :   CHECK_EQ(1, promise_reject_counter);
   18103           5 :   CHECK_EQ(0, promise_revoke_counter);
   18104           5 :   CHECK_EQ(2, promise_reject_frame_count);
   18105           5 :   CHECK_EQ(5, promise_reject_line_number);
   18106           5 :   CHECK_EQ(10, promise_reject_column_number);
   18107           5 :   CHECK_EQ(2, promise_reject_msg_line_number);
   18108          10 :   CHECK_EQ(7, promise_reject_msg_column_number);
   18109           5 : }
   18110             : 
   18111       28342 : TEST(PromiseRejectIsSharedCrossOrigin) {
   18112           5 :   LocalContext env;
   18113           5 :   v8::Isolate* isolate = env->GetIsolate();
   18114          10 :   v8::HandleScope scope(isolate);
   18115             : 
   18116           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   18117             : 
   18118           5 :   ResetPromiseStates();
   18119             : 
   18120             :   // Create promise p0.
   18121             :   CompileRun(
   18122             :       "var reject;            \n"
   18123             :       "var p0 = new Promise(  \n"
   18124             :       "  function(res, rej) { \n"
   18125             :       "    reject = rej;      \n"
   18126             :       "  }                    \n"
   18127             :       ");                     \n");
   18128          10 :   CHECK(!GetPromise("p0")->HasHandler());
   18129           5 :   CHECK_EQ(0, promise_reject_counter);
   18130           5 :   CHECK_EQ(0, promise_revoke_counter);
   18131             :   // Not set because it's not yet rejected.
   18132           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   18133             : 
   18134             :   // Reject p0.
   18135             :   CompileRun("reject('ppp');");
   18136           5 :   CHECK_EQ(1, promise_reject_counter);
   18137           5 :   CHECK_EQ(0, promise_revoke_counter);
   18138             :   // Not set because the ScriptOriginOptions is from the script.
   18139           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   18140             : 
   18141           5 :   ResetPromiseStates();
   18142             : 
   18143             :   // Create promise p1
   18144             :   CompileRun(
   18145             :       "var reject;            \n"
   18146             :       "var p1 = new Promise(  \n"
   18147             :       "  function(res, rej) { \n"
   18148             :       "    reject = rej;      \n"
   18149             :       "  }                    \n"
   18150             :       ");                     \n");
   18151          10 :   CHECK(!GetPromise("p1")->HasHandler());
   18152           5 :   CHECK_EQ(0, promise_reject_counter);
   18153           5 :   CHECK_EQ(0, promise_revoke_counter);
   18154             :   // Not set because it's not yet rejected.
   18155           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   18156             : 
   18157             :   // Add resolve handler (and default reject handler) to p1.
   18158             :   CompileRun("var p2 = p1.then(function(){});");
   18159          10 :   CHECK(GetPromise("p1")->HasHandler());
   18160          10 :   CHECK(!GetPromise("p2")->HasHandler());
   18161           5 :   CHECK_EQ(0, promise_reject_counter);
   18162           5 :   CHECK_EQ(0, promise_revoke_counter);
   18163             : 
   18164             :   // Reject p1.
   18165             :   CompileRun("reject('ppp');");
   18166           5 :   CHECK_EQ(1, promise_reject_counter);
   18167           5 :   CHECK_EQ(0, promise_revoke_counter);
   18168             :   // Set because the event is from an empty script.
   18169          10 :   CHECK(promise_reject_is_shared_cross_origin);
   18170           5 : }
   18171             : 
   18172       28342 : TEST(PromiseRejectMarkAsHandled) {
   18173           5 :   LocalContext env;
   18174           5 :   v8::Isolate* isolate = env->GetIsolate();
   18175          10 :   v8::HandleScope scope(isolate);
   18176             : 
   18177           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   18178             : 
   18179           5 :   ResetPromiseStates();
   18180             : 
   18181             :   // Create promise p0.
   18182             :   CompileRun(
   18183             :       "var reject;            \n"
   18184             :       "var p0 = new Promise(  \n"
   18185             :       "  function(res, rej) { \n"
   18186             :       "    reject = rej;      \n"
   18187             :       "  }                    \n"
   18188             :       ");                     \n");
   18189          10 :   CHECK(!GetPromise("p0")->HasHandler());
   18190           5 :   CHECK_EQ(0, promise_reject_counter);
   18191           5 :   CHECK_EQ(0, promise_revoke_counter);
   18192          10 :   GetPromise("p0")->MarkAsHandled();
   18193             : 
   18194             :   // Reject p0. promise_reject_counter shouldn't be incremented because
   18195             :   // it's marked as handled.
   18196             :   CompileRun("reject('ppp');");
   18197           5 :   CHECK_EQ(0, promise_reject_counter);
   18198          10 :   CHECK_EQ(0, promise_revoke_counter);
   18199           5 : }
   18200          30 : void PromiseRejectCallbackConstructError(
   18201             :     v8::PromiseRejectMessage reject_message) {
   18202          30 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   18203          30 :   CHECK_EQ(v8::Promise::PromiseState::kRejected,
   18204             :            reject_message.GetPromise()->State());
   18205          60 :   USE(v8::Script::Compile(context, v8_str("new Error('test')"))
   18206             :           .ToLocalChecked()
   18207             :           ->Run(context));
   18208          30 : }
   18209             : 
   18210       28342 : TEST(PromiseRejectCallbackConstructError) {
   18211           5 :   i::FLAG_allow_natives_syntax = true;
   18212           5 :   LocalContext env;
   18213           5 :   v8::Isolate* isolate = env->GetIsolate();
   18214          10 :   v8::HandleScope scope(isolate);
   18215             : 
   18216           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallbackConstructError);
   18217             : 
   18218           5 :   ResetPromiseStates();
   18219             :   CompileRun(
   18220             :       "function f(p) {"
   18221             :       "    p.catch(() => {});"
   18222             :       "}"
   18223             :       "f(Promise.reject());"
   18224             :       "f(Promise.reject());"
   18225             :       "%OptimizeFunctionOnNextCall(f);"
   18226             :       "let p = Promise.reject();"
   18227           5 :       "f(p);");
   18228           5 : }
   18229             : 
   18230          10 : void AnalyzeStackOfEvalWithSourceURL(
   18231          80 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18232          10 :   v8::HandleScope scope(args.GetIsolate());
   18233             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18234          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18235          10 :   CHECK_EQ(5, stackTrace->GetFrameCount());
   18236          10 :   v8::Local<v8::String> url = v8_str("eval_url");
   18237          40 :   for (int i = 0; i < 3; i++) {
   18238             :     v8::Local<v8::String> name =
   18239          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   18240          30 :     CHECK(!name.IsEmpty());
   18241          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18242          10 :   }
   18243          10 : }
   18244             : 
   18245             : 
   18246       28342 : TEST(SourceURLInStackTrace) {
   18247           5 :   v8::Isolate* isolate = CcTest::isolate();
   18248           5 :   v8::HandleScope scope(isolate);
   18249           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18250             :   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   18251             :              v8::FunctionTemplate::New(isolate,
   18252          15 :                                        AnalyzeStackOfEvalWithSourceURL));
   18253          10 :   LocalContext context(nullptr, templ);
   18254             : 
   18255             :   const char *source =
   18256             :     "function outer() {\n"
   18257             :     "function bar() {\n"
   18258             :     "  AnalyzeStackOfEvalWithSourceURL();\n"
   18259             :     "}\n"
   18260             :     "function foo() {\n"
   18261             :     "\n"
   18262             :     "  bar();\n"
   18263             :     "}\n"
   18264             :     "foo();\n"
   18265             :     "}\n"
   18266             :     "eval('(' + outer +')()%s');";
   18267             : 
   18268             :   i::ScopedVector<char> code(1024);
   18269           5 :   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   18270           5 :   CHECK(CompileRun(code.start())->IsUndefined());
   18271           5 :   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   18272          10 :   CHECK(CompileRun(code.start())->IsUndefined());
   18273           5 : }
   18274             : 
   18275             : 
   18276             : static int scriptIdInStack[2];
   18277             : 
   18278           5 : void AnalyzeScriptIdInStack(
   18279          20 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18280           5 :   v8::HandleScope scope(args.GetIsolate());
   18281             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18282           5 :       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   18283           5 :   CHECK_EQ(2, stackTrace->GetFrameCount());
   18284          10 :   for (int i = 0; i < 2; i++) {
   18285             :     scriptIdInStack[i] =
   18286          30 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptId();
   18287           5 :   }
   18288           5 : }
   18289             : 
   18290             : 
   18291       28342 : TEST(ScriptIdInStackTrace) {
   18292           5 :   v8::Isolate* isolate = CcTest::isolate();
   18293           5 :   v8::HandleScope scope(isolate);
   18294           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18295             :   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   18296          15 :              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   18297          10 :   LocalContext context(nullptr, templ);
   18298             : 
   18299             :   v8::Local<v8::String> scriptSource = v8_str(
   18300             :       "function foo() {\n"
   18301             :       "  AnalyzeScriptIdInStack();"
   18302             :       "}\n"
   18303           5 :       "foo();\n");
   18304             :   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
   18305           5 :   script->Run(context.local()).ToLocalChecked();
   18306          15 :   for (int i = 0; i < 2; i++) {
   18307          10 :     CHECK_NE(scriptIdInStack[i], v8::Message::kNoScriptIdInfo);
   18308          20 :     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   18309           5 :   }
   18310           5 : }
   18311             : 
   18312             : 
   18313          10 : void AnalyzeStackOfInlineScriptWithSourceURL(
   18314          80 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18315          10 :   v8::HandleScope scope(args.GetIsolate());
   18316             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18317          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18318          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   18319          10 :   v8::Local<v8::String> url = v8_str("source_url");
   18320          40 :   for (int i = 0; i < 3; i++) {
   18321             :     v8::Local<v8::String> name =
   18322          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   18323          30 :     CHECK(!name.IsEmpty());
   18324          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18325          10 :   }
   18326          10 : }
   18327             : 
   18328             : 
   18329       28342 : TEST(InlineScriptWithSourceURLInStackTrace) {
   18330           5 :   v8::Isolate* isolate = CcTest::isolate();
   18331           5 :   v8::HandleScope scope(isolate);
   18332           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18333             :   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   18334             :              v8::FunctionTemplate::New(
   18335          15 :                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   18336          10 :   LocalContext context(nullptr, templ);
   18337             : 
   18338             :   const char *source =
   18339             :     "function outer() {\n"
   18340             :     "function bar() {\n"
   18341             :     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   18342             :     "}\n"
   18343             :     "function foo() {\n"
   18344             :     "\n"
   18345             :     "  bar();\n"
   18346             :     "}\n"
   18347             :     "foo();\n"
   18348             :     "}\n"
   18349             :     "outer()\n%s";
   18350             : 
   18351             :   i::ScopedVector<char> code(1024);
   18352           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18353          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   18354           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   18355          15 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   18356           5 : }
   18357             : 
   18358         395 : void SetPromise(const char* name, v8::Local<v8::Promise> promise) {
   18359             :   CcTest::global()
   18360        1185 :       ->Set(CcTest::isolate()->GetCurrentContext(), v8_str(name), promise)
   18361         790 :       .FromJust();
   18362         395 : }
   18363             : 
   18364           5 : class PromiseHookData {
   18365             :  public:
   18366             :   int before_hook_count = 0;
   18367             :   int after_hook_count = 0;
   18368             :   int promise_hook_count = 0;
   18369             :   int parent_promise_count = 0;
   18370             :   bool check_value = true;
   18371             :   std::string promise_hook_value;
   18372             : 
   18373             :   void Reset() {
   18374          50 :     before_hook_count = 0;
   18375          50 :     after_hook_count = 0;
   18376          50 :     promise_hook_count = 0;
   18377          50 :     parent_promise_count = 0;
   18378          50 :     check_value = true;
   18379          50 :     promise_hook_value = "";
   18380             :   }
   18381             : };
   18382             : 
   18383             : PromiseHookData* promise_hook_data;
   18384             : 
   18385         350 : void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise,
   18386             :                        v8::Local<v8::Value> parentPromise) {
   18387         350 :   promise_hook_data->promise_hook_count++;
   18388         350 :   switch (type) {
   18389             :     case v8::PromiseHookType::kInit:
   18390         125 :       SetPromise("init", promise);
   18391             : 
   18392         125 :       if (!parentPromise->IsUndefined()) {
   18393          45 :         promise_hook_data->parent_promise_count++;
   18394          45 :         SetPromise("parent", v8::Local<v8::Promise>::Cast(parentPromise));
   18395             :       }
   18396             : 
   18397             :       break;
   18398             :     case v8::PromiseHookType::kResolve:
   18399         125 :       SetPromise("resolve", promise);
   18400         125 :       break;
   18401             :     case v8::PromiseHookType::kBefore:
   18402          50 :       promise_hook_data->before_hook_count++;
   18403          50 :       CHECK(promise_hook_data->before_hook_count >
   18404             :             promise_hook_data->after_hook_count);
   18405         300 :       CHECK(CcTest::global()
   18406             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18407             :                 .ToLocalChecked()
   18408             :                 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str(""))
   18409             :                 .FromJust());
   18410          50 :       SetPromise("before", promise);
   18411          50 :       break;
   18412             :     case v8::PromiseHookType::kAfter:
   18413          50 :       promise_hook_data->after_hook_count++;
   18414          50 :       CHECK(promise_hook_data->after_hook_count <=
   18415             :             promise_hook_data->before_hook_count);
   18416          50 :       if (promise_hook_data->check_value) {
   18417         180 :         CHECK(
   18418             :             CcTest::global()
   18419             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18420             :                 .ToLocalChecked()
   18421             :                 ->Equals(CcTest::isolate()->GetCurrentContext(),
   18422             :                          v8_str(promise_hook_data->promise_hook_value.c_str()))
   18423             :                 .FromJust());
   18424             :       }
   18425          50 :       SetPromise("after", promise);
   18426          50 :       break;
   18427             :   }
   18428         350 : }
   18429             : 
   18430       28342 : TEST(PromiseHook) {
   18431           5 :   LocalContext env;
   18432           5 :   v8::Isolate* isolate = env->GetIsolate();
   18433          10 :   v8::HandleScope scope(isolate);
   18434             : 
   18435           5 :   v8::Local<v8::Object> global = CcTest::global();
   18436           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   18437             : 
   18438          10 :   promise_hook_data = new PromiseHookData();
   18439           5 :   isolate->SetPromiseHook(CustomPromiseHook);
   18440             : 
   18441             :   // Test that an initialized promise is passed to init. Other hooks
   18442             :   // can not have un initialized promise.
   18443           5 :   promise_hook_data->check_value = false;
   18444             :   CompileRun("var p = new Promise(() => {});");
   18445             : 
   18446          15 :   auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18447          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18448             :   auto init_promise_obj = v8::Local<v8::Promise>::Cast(init_promise);
   18449           5 :   CHECK_EQ(init_promise_obj->State(), v8::Promise::PromiseState::kPending);
   18450           5 :   CHECK(!init_promise_obj->HasHandler());
   18451             : 
   18452           5 :   promise_hook_data->Reset();
   18453           5 :   promise_hook_data->promise_hook_value = "fulfilled";
   18454             :   const char* source =
   18455             :       "var resolve, value = ''; \n"
   18456             :       "var p = new Promise(r => resolve = r); \n";
   18457             : 
   18458             :   CompileRun(source);
   18459          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18460          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18461           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18462           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18463             : 
   18464             :   CompileRun("var p1 = p.then(() => { value = 'fulfilled'; }); \n");
   18465          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18466          15 :   auto parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18467          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   18468          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   18469           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18470           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   18471             : 
   18472             :   CompileRun("resolve(); \n");
   18473             :   auto resolve_promise =
   18474          15 :       global->Get(context, v8_str("resolve")).ToLocalChecked();
   18475          15 :   auto before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18476          15 :   auto after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18477          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18478          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18479          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18480           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18481             : 
   18482             :   CompileRun("value = ''; var p2 = p1.then(() => { value = 'fulfilled' }); \n");
   18483          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18484          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18485          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18486          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18487          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18488          15 :   CHECK(GetPromise("p2")->Equals(env.local(), init_promise).FromJust());
   18489          15 :   CHECK(GetPromise("p1")->Equals(env.local(), parent_promise).FromJust());
   18490          15 :   CHECK(GetPromise("p2")->Equals(env.local(), before_promise).FromJust());
   18491          15 :   CHECK(GetPromise("p2")->Equals(env.local(), after_promise).FromJust());
   18492          15 :   CHECK(GetPromise("p2")->Equals(env.local(), resolve_promise).FromJust());
   18493           5 :   CHECK_EQ(10, promise_hook_data->promise_hook_count);
   18494             : 
   18495             :   promise_hook_data->Reset();
   18496           5 :   promise_hook_data->promise_hook_value = "rejected";
   18497             :   source =
   18498             :       "var reject, value = ''; \n"
   18499             :       "var p = new Promise((_, r) => reject = r); \n";
   18500             : 
   18501             :   CompileRun(source);
   18502          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18503          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18504           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18505           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18506             : 
   18507             :   CompileRun("var p1 = p.catch(() => { value = 'rejected'; }); \n");
   18508          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18509          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18510          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   18511          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   18512           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18513           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   18514             : 
   18515             :   CompileRun("reject(); \n");
   18516          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18517          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18518          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18519          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18520          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18521          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18522           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18523             : 
   18524             :   promise_hook_data->Reset();
   18525           5 :   promise_hook_data->promise_hook_value = "Promise.resolve";
   18526             :   source =
   18527             :       "var value = ''; \n"
   18528             :       "var p = Promise.resolve('Promise.resolve'); \n";
   18529             : 
   18530             :   CompileRun(source);
   18531          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18532          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18533             :   // init hook and resolve hook
   18534           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18535           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18536          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18537          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   18538             : 
   18539             :   CompileRun("var p1 = p.then((v) => { value = v; }); \n");
   18540          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18541          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18542          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   18543          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18544          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18545          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   18546          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18547          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   18548          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18549          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18550           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18551           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   18552             : 
   18553             :   promise_hook_data->Reset();
   18554             :   source =
   18555             :       "var resolve, value = ''; \n"
   18556             :       "var p = new Promise((_, r) => resolve = r); \n";
   18557             : 
   18558             :   CompileRun(source);
   18559          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18560          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18561           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18562           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18563             : 
   18564             :   CompileRun("resolve(); \n");
   18565          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18566          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   18567           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18568             : 
   18569             :   promise_hook_data->Reset();
   18570             :   source =
   18571             :       "var reject, value = ''; \n"
   18572             :       "var p = new Promise((_, r) => reject = r); \n";
   18573             : 
   18574             :   CompileRun(source);
   18575          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   18576          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   18577           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18578           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   18579             : 
   18580             :   CompileRun("reject(); \n");
   18581          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18582          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   18583           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18584             : 
   18585             :   promise_hook_data->Reset();
   18586             :   // This test triggers after callbacks right after each other, so
   18587             :   // lets just check the value at the end.
   18588           5 :   promise_hook_data->check_value = false;
   18589           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   18590             :   source =
   18591             :       "var resolve, value = ''; \n"
   18592             :       "var tempPromise = new Promise(r => resolve = r); \n"
   18593             :       "var p = Promise.all([tempPromise]);\n "
   18594             :       "var p1 = p.then(v => value = v[0]); \n";
   18595             : 
   18596             :   CompileRun(source);
   18597             :   // 1) init hook (tempPromise)
   18598             :   // 2) init hook (p)
   18599             :   // 3) init hook (throwaway Promise in Promise.all, p)
   18600             :   // 4) init hook (p1, p)
   18601           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   18602           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   18603             : 
   18604           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   18605             :   CompileRun("resolve('Promise.all'); \n");
   18606          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18607          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18608             :   // 5) resolve hook (tempPromise)
   18609             :   // 6) resolve hook (throwaway Promise in Promise.all)
   18610             :   // 6) before hook (throwaway Promise in Promise.all)
   18611             :   // 7) after hook (throwaway Promise in Promise.all)
   18612             :   // 8) before hook (p)
   18613             :   // 9) after hook (p)
   18614             :   // 10) resolve hook (p1)
   18615             :   // 11) before hook (p1)
   18616             :   // 12) after hook (p1)
   18617           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   18618          30 :   CHECK(CcTest::global()
   18619             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18620             :             .ToLocalChecked()
   18621             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   18622             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   18623             :             .FromJust());
   18624             : 
   18625           5 :   promise_hook_data->Reset();
   18626             :   // This test triggers after callbacks right after each other, so
   18627             :   // lets just check the value at the end.
   18628           5 :   promise_hook_data->check_value = false;
   18629           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   18630             :   source =
   18631             :       "var resolve, value = ''; \n"
   18632             :       "var tempPromise = new Promise(r => resolve = r); \n"
   18633             :       "var p = Promise.race([tempPromise]);\n "
   18634             :       "var p1 = p.then(v => value = v); \n";
   18635             : 
   18636             :   CompileRun(source);
   18637             :   // 1) init hook (tempPromise)
   18638             :   // 2) init hook (p)
   18639             :   // 3) init hook (throwaway Promise in Promise.race, p)
   18640             :   // 4) init hook (p1, p)
   18641           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   18642           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   18643             : 
   18644           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   18645             :   CompileRun("resolve('Promise.race'); \n");
   18646          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18647          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18648             :   // 5) resolve hook (tempPromise)
   18649             :   // 6) resolve hook (throwaway Promise in Promise.race)
   18650             :   // 6) before hook (throwaway Promise in Promise.race)
   18651             :   // 7) after hook (throwaway Promise in Promise.race)
   18652             :   // 8) before hook (p)
   18653             :   // 9) after hook (p)
   18654             :   // 10) resolve hook (p1)
   18655             :   // 11) before hook (p1)
   18656             :   // 12) after hook (p1)
   18657           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   18658          30 :   CHECK(CcTest::global()
   18659             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18660             :             .ToLocalChecked()
   18661             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   18662             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   18663             :             .FromJust());
   18664             : 
   18665           5 :   promise_hook_data->Reset();
   18666           5 :   promise_hook_data->promise_hook_value = "subclass";
   18667             :   source =
   18668             :       "var resolve, value = '';\n"
   18669             :       "class MyPromise extends Promise { \n"
   18670             :       "  then(onFulfilled, onRejected) { \n"
   18671             :       "      return super.then(onFulfilled, onRejected); \n"
   18672             :       "  };\n"
   18673             :       "};\n"
   18674             :       "var p = new MyPromise(r => resolve = r);\n";
   18675             : 
   18676             :   CompileRun(source);
   18677             :   // 1) init hook (p)
   18678           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18679             : 
   18680             :   CompileRun("var p1 = p.then(() => value = 'subclass');\n");
   18681             :   // 2) init hook (p1)
   18682           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18683             : 
   18684             :   CompileRun("resolve();\n");
   18685          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18686          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18687          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18688          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18689          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18690          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18691             :   // 3) resolve hook (p)
   18692             :   // 4) before hook (p)
   18693             :   // 5) after hook (p)
   18694             :   // 6) resolve hook (p1)
   18695           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18696             : 
   18697             :   promise_hook_data->Reset();
   18698             :   source =
   18699             :       "class X extends Promise {\n"
   18700             :       "  static get [Symbol.species]() {\n"
   18701             :       "    return Y;\n"
   18702             :       "  }\n"
   18703             :       "}\n"
   18704             :       "class Y {\n"
   18705             :       "  constructor(executor) {\n"
   18706             :       "    return new Proxy(new Promise(executor), {});\n"
   18707             :       "  }\n"
   18708             :       "}\n"
   18709             :       "var x = X.resolve().then(() => {});\n";
   18710             : 
   18711             :   CompileRun(source);
   18712             : 
   18713           5 :   promise_hook_data->Reset();
   18714             :   source =
   18715             :       "var resolve, value = '';\n"
   18716             :       "var p = new Promise(r => resolve = r);\n";
   18717             : 
   18718             :   CompileRun(source);
   18719          10 :   CHECK_EQ(v8::Promise::kPending, GetPromise("p")->State());
   18720             :   CompileRun("resolve(Promise.resolve(value));\n");
   18721          10 :   CHECK_EQ(v8::Promise::kFulfilled, GetPromise("p")->State());
   18722           5 :   CHECK_EQ(9, promise_hook_data->promise_hook_count);
   18723             : 
   18724          10 :   delete promise_hook_data;
   18725          10 :   isolate->SetPromiseHook(nullptr);
   18726           5 : }
   18727             : 
   18728          10 : void AnalyzeStackOfDynamicScriptWithSourceURL(
   18729          80 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18730          10 :   v8::HandleScope scope(args.GetIsolate());
   18731             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18732          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18733          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   18734          10 :   v8::Local<v8::String> url = v8_str("source_url");
   18735          40 :   for (int i = 0; i < 3; i++) {
   18736             :     v8::Local<v8::String> name =
   18737          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   18738          30 :     CHECK(!name.IsEmpty());
   18739          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18740          10 :   }
   18741          10 : }
   18742             : 
   18743             : 
   18744       28342 : TEST(DynamicWithSourceURLInStackTrace) {
   18745           5 :   v8::Isolate* isolate = CcTest::isolate();
   18746           5 :   v8::HandleScope scope(isolate);
   18747           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18748             :   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   18749             :              v8::FunctionTemplate::New(
   18750          15 :                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   18751          10 :   LocalContext context(nullptr, templ);
   18752             : 
   18753             :   const char *source =
   18754             :     "function outer() {\n"
   18755             :     "function bar() {\n"
   18756             :     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   18757             :     "}\n"
   18758             :     "function foo() {\n"
   18759             :     "\n"
   18760             :     "  bar();\n"
   18761             :     "}\n"
   18762             :     "foo();\n"
   18763             :     "}\n"
   18764             :     "outer()\n%s";
   18765             : 
   18766             :   i::ScopedVector<char> code(1024);
   18767           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18768          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18769           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   18770          15 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18771           5 : }
   18772             : 
   18773             : 
   18774       28342 : TEST(DynamicWithSourceURLInStackTraceString) {
   18775           5 :   LocalContext context;
   18776          10 :   v8::HandleScope scope(context->GetIsolate());
   18777             : 
   18778             :   const char *source =
   18779             :     "function outer() {\n"
   18780             :     "  function foo() {\n"
   18781             :     "    FAIL.FAIL;\n"
   18782             :     "  }\n"
   18783             :     "  foo();\n"
   18784             :     "}\n"
   18785             :     "outer()\n%s";
   18786             : 
   18787             :   i::ScopedVector<char> code(1024);
   18788           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18789          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18790           5 :   CompileRunWithOrigin(code.start(), "", 0, 0);
   18791           5 :   CHECK(try_catch.HasCaught());
   18792             :   v8::String::Utf8Value stack(
   18793             :       context->GetIsolate(),
   18794          15 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   18795          15 :   CHECK_NOT_NULL(strstr(*stack, "at foo (source_url:3:5)"));
   18796           5 : }
   18797             : 
   18798             : 
   18799       28342 : TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18800           5 :   LocalContext context;
   18801          10 :   v8::HandleScope scope(context->GetIsolate());
   18802             : 
   18803             :   const char *source =
   18804             :     "function outer() {\n"
   18805             :     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   18806             :     "  //# sourceURL=source_url\";\n"
   18807             :     "  eval(scriptContents);\n"
   18808             :     "  foo(); }\n"
   18809             :     "outer();\n"
   18810             :     "//# sourceURL=outer_url";
   18811             : 
   18812          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18813             :   CompileRun(source);
   18814           5 :   CHECK(try_catch.HasCaught());
   18815             : 
   18816           5 :   Local<v8::Message> message = try_catch.Message();
   18817           5 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18818           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18819           5 :                      "source_url"));
   18820           5 : }
   18821             : 
   18822             : 
   18823       28342 : TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18824           5 :   LocalContext context;
   18825          10 :   v8::HandleScope scope(context->GetIsolate());
   18826             : 
   18827             :   const char *source =
   18828             :     "function outer() {\n"
   18829             :     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   18830             :     "  //# sourceURL=source_url\";\n"
   18831             :     "  eval(scriptContents);\n"
   18832             :     "  boo(); }\n"
   18833             :     "outer();\n"
   18834             :     "//# sourceURL=outer_url";
   18835             : 
   18836          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18837             :   CompileRun(source);
   18838           5 :   CHECK(try_catch.HasCaught());
   18839             : 
   18840           5 :   Local<v8::Message> message = try_catch.Message();
   18841           5 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18842           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18843           5 :                      "source_url"));
   18844           5 : }
   18845             : 
   18846             : 
   18847           5 : static void CreateGarbageInOldSpace() {
   18848             :   i::Factory* factory = CcTest::i_isolate()->factory();
   18849           5 :   v8::HandleScope scope(CcTest::isolate());
   18850             :   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   18851        5005 :   for (int i = 0; i < 1000; i++) {
   18852        5000 :     factory->NewFixedArray(1000, i::TENURED);
   18853           5 :   }
   18854           5 : }
   18855             : 
   18856             : 
   18857             : // Test that idle notification can be handled and eventually collects garbage.
   18858       28342 : TEST(TestIdleNotification) {
   18859           5 :   if (!i::FLAG_incremental_marking) return;
   18860             :   ManualGCScope manual_gc_scope;
   18861             :   const intptr_t MB = 1024 * 1024;
   18862             :   const double IdlePauseInSeconds = 1.0;
   18863          10 :   LocalContext env;
   18864          10 :   v8::HandleScope scope(env->GetIsolate());
   18865           5 :   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   18866           5 :   CreateGarbageInOldSpace();
   18867           5 :   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   18868           5 :   CHECK_GT(size_with_garbage, initial_size + MB);
   18869             :   bool finished = false;
   18870          10 :   for (int i = 0; i < 200 && !finished; i++) {
   18871          20 :     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
   18872             :       CcTest::heap()->StartIdleIncrementalMarking(
   18873           5 :           i::GarbageCollectionReason::kTesting);
   18874             :     }
   18875             :     finished = env->GetIsolate()->IdleNotificationDeadline(
   18876          30 :         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   18877             :          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   18878          20 :         IdlePauseInSeconds);
   18879          20 :     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
   18880           5 :       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
   18881             :     }
   18882             :   }
   18883           5 :   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   18884           5 :   CHECK(finished);
   18885           5 :   CHECK_LT(final_size, initial_size + 1);
   18886             : }
   18887             : 
   18888       28342 : TEST(TestMemorySavingsMode) {
   18889           5 :   LocalContext context;
   18890           5 :   v8::Isolate* isolate = context->GetIsolate();
   18891          15 :   v8::internal::Isolate* i_isolate =
   18892             :       reinterpret_cast<v8::internal::Isolate*>(isolate);
   18893           5 :   CHECK(!i_isolate->IsMemorySavingsModeActive());
   18894           5 :   isolate->EnableMemorySavingsMode();
   18895           5 :   CHECK(i_isolate->IsMemorySavingsModeActive());
   18896           5 :   isolate->DisableMemorySavingsMode();
   18897           5 :   CHECK(!i_isolate->IsMemorySavingsModeActive());
   18898           5 : }
   18899             : 
   18900       28342 : TEST(Regress2333) {
   18901           5 :   LocalContext env;
   18902          20 :   for (int i = 0; i < 3; i++) {
   18903          15 :     CcTest::CollectGarbage(i::NEW_SPACE);
   18904           5 :   }
   18905           5 : }
   18906             : 
   18907             : static uint32_t* stack_limit;
   18908             : 
   18909          10 : static void GetStackLimitCallback(
   18910             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18911             :   stack_limit = reinterpret_cast<uint32_t*>(
   18912          10 :       CcTest::i_isolate()->stack_guard()->real_climit());
   18913          10 : }
   18914             : 
   18915             : 
   18916             : // Uses the address of a local variable to determine the stack top now.
   18917             : // Given a size, returns an address that is that far from the current
   18918             : // top of stack.
   18919             : static uint32_t* ComputeStackLimit(uint32_t size) {
   18920             :   uint32_t* answer = &size - (size / sizeof(size));
   18921             :   // If the size is very large and the stack is very near the bottom of
   18922             :   // memory then the calculation above may wrap around and give an address
   18923             :   // that is above the (downwards-growing) stack.  In that case we return
   18924             :   // a very low address.
   18925             :   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   18926             :   return answer;
   18927             : }
   18928             : 
   18929             : 
   18930             : // We need at least 165kB for an x64 debug build with clang and ASAN.
   18931             : static const int stack_breathing_room = 256 * i::KB;
   18932             : 
   18933             : 
   18934       28342 : TEST(SetStackLimit) {
   18935             :   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   18936             : 
   18937             :   // Set stack limit.
   18938           5 :   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18939             : 
   18940             :   // Execute a script.
   18941           5 :   LocalContext env;
   18942          10 :   v8::HandleScope scope(env->GetIsolate());
   18943             :   Local<v8::FunctionTemplate> fun_templ =
   18944           5 :       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   18945          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18946          25 :   CHECK(env->Global()
   18947             :             ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18948             :             .FromJust());
   18949             :   CompileRun("get_stack_limit();");
   18950             : 
   18951          10 :   CHECK(stack_limit == set_limit);
   18952           5 : }
   18953             : 
   18954             : 
   18955       28342 : TEST(SetStackLimitInThread) {
   18956             :   uint32_t* set_limit;
   18957             :   {
   18958           5 :     v8::Locker locker(CcTest::isolate());
   18959             :     set_limit = ComputeStackLimit(stack_breathing_room);
   18960             : 
   18961             :     // Set stack limit.
   18962           5 :     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18963             : 
   18964             :     // Execute a script.
   18965          10 :     v8::HandleScope scope(CcTest::isolate());
   18966          10 :     LocalContext env;
   18967             :     Local<v8::FunctionTemplate> fun_templ =
   18968           5 :         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   18969          10 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18970          25 :     CHECK(env->Global()
   18971             :               ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18972             :               .FromJust());
   18973             :     CompileRun("get_stack_limit();");
   18974             : 
   18975          10 :     CHECK(stack_limit == set_limit);
   18976             :   }
   18977             :   {
   18978           5 :     v8::Locker locker(CcTest::isolate());
   18979           5 :     CHECK(stack_limit == set_limit);
   18980             :   }
   18981           5 : }
   18982             : 
   18983       28343 : THREADED_TEST(GetHeapStatistics) {
   18984           6 :   LocalContext c1;
   18985          12 :   v8::HandleScope scope(c1->GetIsolate());
   18986           6 :   v8::HeapStatistics heap_statistics;
   18987           6 :   CHECK_EQ(0u, heap_statistics.total_heap_size());
   18988           6 :   CHECK_EQ(0u, heap_statistics.used_heap_size());
   18989           6 :   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   18990           6 :   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   18991          12 :   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   18992           6 : }
   18993             : 
   18994       28342 : TEST(GetHeapSpaceStatistics) {
   18995           5 :   LocalContext c1;
   18996           5 :   v8::Isolate* isolate = c1->GetIsolate();
   18997          10 :   v8::HandleScope scope(isolate);
   18998           5 :   v8::HeapStatistics heap_statistics;
   18999             : 
   19000             :   // Force allocation in LO_SPACE so that every space has non-zero size.
   19001             :   v8::internal::Isolate* i_isolate =
   19002             :       reinterpret_cast<v8::internal::Isolate*>(isolate);
   19003           5 :   auto unused = i_isolate->factory()->TryNewFixedArray(512 * 1024, i::TENURED);
   19004             :   USE(unused);
   19005             : 
   19006           5 :   isolate->GetHeapStatistics(&heap_statistics);
   19007             : 
   19008             :   // Ensure that the sum of all the spaces matches the totals from
   19009             :   // GetHeapSpaceStatics.
   19010             :   size_t total_size = 0u;
   19011             :   size_t total_used_size = 0u;
   19012             :   size_t total_available_size = 0u;
   19013             :   size_t total_physical_size = 0u;
   19014          45 :   for (size_t i = 0; i < isolate->NumberOfHeapSpaces(); ++i) {
   19015          40 :     v8::HeapSpaceStatistics space_statistics;
   19016          40 :     isolate->GetHeapSpaceStatistics(&space_statistics, i);
   19017          40 :     CHECK_NOT_NULL(space_statistics.space_name());
   19018          75 :     if (strcmp(space_statistics.space_name(), "new_large_object_space") == 0 ||
   19019          35 :         strcmp(space_statistics.space_name(), "code_large_object_space") == 0) {
   19020          10 :       continue;
   19021             :     }
   19022          30 :     CHECK_GT(space_statistics.space_size(), 0u);
   19023          30 :     total_size += space_statistics.space_size();
   19024          30 :     CHECK_GT(space_statistics.space_used_size(), 0u);
   19025          30 :     total_used_size += space_statistics.space_used_size();
   19026          30 :     total_available_size += space_statistics.space_available_size();
   19027          30 :     CHECK_GT(space_statistics.physical_space_size(), 0u);
   19028          30 :     total_physical_size += space_statistics.physical_space_size();
   19029             :   }
   19030          10 :   total_available_size += CcTest::heap()->memory_allocator()->Available();
   19031             : 
   19032           5 :   CHECK_EQ(total_size, heap_statistics.total_heap_size());
   19033           5 :   CHECK_EQ(total_used_size, heap_statistics.used_heap_size());
   19034           5 :   CHECK_EQ(total_available_size, heap_statistics.total_available_size());
   19035          10 :   CHECK_EQ(total_physical_size, heap_statistics.total_physical_size());
   19036           5 : }
   19037             : 
   19038       28342 : TEST(NumberOfNativeContexts) {
   19039             :   static const size_t kNumTestContexts = 10;
   19040             :   i::Isolate* isolate = CcTest::i_isolate();
   19041             :   i::HandleScope scope(isolate);
   19042         110 :   v8::Global<v8::Context> context[kNumTestContexts];
   19043           5 :   v8::HeapStatistics heap_statistics;
   19044           5 :   CHECK_EQ(0u, heap_statistics.number_of_native_contexts());
   19045           5 :   CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   19046           5 :   CHECK_EQ(0u, heap_statistics.number_of_native_contexts());
   19047          55 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   19048             :     i::HandleScope inner(isolate);
   19049         100 :     context[i].Reset(CcTest::isolate(), v8::Context::New(CcTest::isolate()));
   19050          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   19051          50 :     CHECK_EQ(i + 1, heap_statistics.number_of_native_contexts());
   19052             :   }
   19053          50 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   19054          50 :     context[i].Reset();
   19055          50 :     CcTest::PreciseCollectAllGarbage();
   19056          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   19057          50 :     CHECK_EQ(kNumTestContexts - i - 1u,
   19058             :              heap_statistics.number_of_native_contexts());
   19059             :   }
   19060           5 : }
   19061             : 
   19062       28342 : TEST(NumberOfDetachedContexts) {
   19063             :   static const size_t kNumTestContexts = 10;
   19064             :   i::Isolate* isolate = CcTest::i_isolate();
   19065             :   i::HandleScope scope(isolate);
   19066         110 :   v8::Global<v8::Context> context[kNumTestContexts];
   19067           5 :   v8::HeapStatistics heap_statistics;
   19068           5 :   CHECK_EQ(0u, heap_statistics.number_of_detached_contexts());
   19069           5 :   CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   19070           5 :   CHECK_EQ(0u, heap_statistics.number_of_detached_contexts());
   19071          55 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   19072             :     i::HandleScope inner(isolate);
   19073          50 :     v8::Local<v8::Context> local = v8::Context::New(CcTest::isolate());
   19074          50 :     context[i].Reset(CcTest::isolate(), local);
   19075          50 :     local->DetachGlobal();
   19076          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   19077          50 :     CHECK_EQ(i + 1, heap_statistics.number_of_detached_contexts());
   19078             :   }
   19079          50 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   19080          50 :     context[i].Reset();
   19081          50 :     CcTest::PreciseCollectAllGarbage();
   19082          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   19083          50 :     CHECK_EQ(kNumTestContexts - i - 1u,
   19084             :              heap_statistics.number_of_detached_contexts());
   19085             :   }
   19086           5 : }
   19087             : 
   19088             : class VisitorImpl : public v8::ExternalResourceVisitor {
   19089             :  public:
   19090           5 :   explicit VisitorImpl(TestResource** resource) {
   19091          20 :     for (int i = 0; i < 4; i++) {
   19092          20 :       resource_[i] = resource[i];
   19093          20 :       found_resource_[i] = false;
   19094             :     }
   19095             :   }
   19096           5 :   ~VisitorImpl() override = default;
   19097          25 :   void VisitExternalString(v8::Local<v8::String> string) override {
   19098          25 :     if (!string->IsExternal()) {
   19099           5 :       CHECK(string->IsExternalOneByte());
   19100          25 :       return;
   19101             :     }
   19102             :     v8::String::ExternalStringResource* resource =
   19103             :         string->GetExternalStringResource();
   19104          20 :     CHECK(resource);
   19105          80 :     for (int i = 0; i < 4; i++) {
   19106          80 :       if (resource_[i] == resource) {
   19107          20 :         CHECK(!found_resource_[i]);
   19108          20 :         found_resource_[i] = true;
   19109             :       }
   19110             :     }
   19111             :   }
   19112           5 :   void CheckVisitedResources() {
   19113          25 :     for (int i = 0; i < 4; i++) {
   19114          20 :       CHECK(found_resource_[i]);
   19115             :     }
   19116           5 :   }
   19117             : 
   19118             :  private:
   19119             :   v8::String::ExternalStringResource* resource_[4];
   19120             :   bool found_resource_[4];
   19121             : };
   19122             : 
   19123             : 
   19124       28342 : TEST(ExternalizeOldSpaceTwoByteCons) {
   19125           5 :   v8::Isolate* isolate = CcTest::isolate();
   19126           5 :   LocalContext env;
   19127          10 :   v8::HandleScope scope(isolate);
   19128             :   v8::Local<v8::String> cons =
   19129             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   19130           5 :           ->ToString(env.local())
   19131           5 :           .ToLocalChecked();
   19132          10 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   19133           5 :   CcTest::CollectAllAvailableGarbage();
   19134           5 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   19135             : 
   19136             :   TestResource* resource = new TestResource(
   19137           5 :       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   19138           5 :   cons->MakeExternal(resource);
   19139             : 
   19140           5 :   CHECK(cons->IsExternal());
   19141           5 :   CHECK_EQ(resource, cons->GetExternalStringResource());
   19142             :   String::Encoding encoding;
   19143           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   19144          10 :   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   19145           5 : }
   19146             : 
   19147             : 
   19148       28342 : TEST(ExternalizeOldSpaceOneByteCons) {
   19149           5 :   v8::Isolate* isolate = CcTest::isolate();
   19150           5 :   LocalContext env;
   19151          10 :   v8::HandleScope scope(isolate);
   19152             :   v8::Local<v8::String> cons =
   19153             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   19154           5 :           ->ToString(env.local())
   19155           5 :           .ToLocalChecked();
   19156          10 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   19157           5 :   CcTest::CollectAllAvailableGarbage();
   19158           5 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   19159             : 
   19160             :   TestOneByteResource* resource =
   19161           5 :       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   19162           5 :   cons->MakeExternal(resource);
   19163             : 
   19164           5 :   CHECK(cons->IsExternalOneByte());
   19165           5 :   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   19166             :   String::Encoding encoding;
   19167           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   19168          10 :   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   19169           5 : }
   19170             : 
   19171             : 
   19172       28342 : TEST(VisitExternalStrings) {
   19173           5 :   v8::Isolate* isolate = CcTest::isolate();
   19174           5 :   LocalContext env;
   19175          10 :   v8::HandleScope scope(isolate);
   19176             :   const char* string = "Some string";
   19177           5 :   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   19178             :   TestResource* resource[4];
   19179          10 :   resource[0] = new TestResource(two_byte_string);
   19180             :   v8::Local<v8::String> string0 =
   19181           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
   19182           5 :           .ToLocalChecked();
   19183          10 :   resource[1] = new TestResource(two_byte_string, nullptr, false);
   19184             :   v8::Local<v8::String> string1 =
   19185           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
   19186           5 :           .ToLocalChecked();
   19187             : 
   19188             :   // Externalized symbol.
   19189          10 :   resource[2] = new TestResource(two_byte_string, nullptr, false);
   19190             :   v8::Local<v8::String> string2 =
   19191             :       v8::String::NewFromUtf8(env->GetIsolate(), string,
   19192           5 :                               v8::NewStringType::kInternalized)
   19193           5 :           .ToLocalChecked();
   19194           5 :   CHECK(string2->MakeExternal(resource[2]));
   19195             : 
   19196             :   // Symbolized External.
   19197          10 :   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   19198             :   v8::Local<v8::String> string3 =
   19199           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
   19200           5 :           .ToLocalChecked();
   19201           5 :   CcTest::CollectAllAvailableGarbage();  // Tenure string.
   19202             :   // Turn into a symbol.
   19203             :   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   19204          10 :   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   19205             :       string3_i).is_null());
   19206          10 :   CHECK(string3_i->IsInternalizedString());
   19207             : 
   19208             :   // We need to add usages for string* to avoid warnings in GCC 4.7
   19209           5 :   CHECK(string0->IsExternal());
   19210           5 :   CHECK(string1->IsExternal());
   19211           5 :   CHECK(string2->IsExternal());
   19212           5 :   CHECK(string3->IsExternal());
   19213             : 
   19214             :   VisitorImpl visitor(resource);
   19215           5 :   isolate->VisitExternalResources(&visitor);
   19216          10 :   visitor.CheckVisitedResources();
   19217           5 : }
   19218             : 
   19219             : 
   19220       28342 : TEST(ExternalStringCollectedAtTearDown) {
   19221           5 :   int destroyed = 0;
   19222             :   v8::Isolate::CreateParams create_params;
   19223           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19224           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19225             :   { v8::Isolate::Scope isolate_scope(isolate);
   19226          10 :     v8::HandleScope handle_scope(isolate);
   19227             :     const char* s = "One string to test them all, one string to find them.";
   19228             :     TestOneByteResource* inscription =
   19229           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   19230             :     v8::Local<v8::String> ring =
   19231           5 :         v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
   19232             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   19233           5 :     CHECK_EQ(0, destroyed);
   19234             :     USE(ring);
   19235             :   }
   19236             : 
   19237           5 :   isolate->Dispose();
   19238             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   19239           5 :   CHECK_EQ(1, destroyed);
   19240           5 : }
   19241             : 
   19242             : 
   19243       28342 : TEST(ExternalInternalizedStringCollectedAtTearDown) {
   19244           5 :   int destroyed = 0;
   19245             :   v8::Isolate::CreateParams create_params;
   19246           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19247           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19248             :   { v8::Isolate::Scope isolate_scope(isolate);
   19249           5 :     LocalContext env(isolate);
   19250          10 :     v8::HandleScope handle_scope(isolate);
   19251             :     CompileRun("var ring = 'One string to test them all';");
   19252             :     const char* s = "One string to test them all";
   19253             :     TestOneByteResource* inscription =
   19254           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   19255             :     v8::Local<v8::String> ring =
   19256          10 :         CompileRun("ring")->ToString(env.local()).ToLocalChecked();
   19257          10 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   19258           5 :     ring->MakeExternal(inscription);
   19259             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   19260           5 :     CHECK_EQ(0, destroyed);
   19261             :     USE(ring);
   19262             :   }
   19263             : 
   19264           5 :   isolate->Dispose();
   19265             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   19266           5 :   CHECK_EQ(1, destroyed);
   19267           5 : }
   19268             : 
   19269             : 
   19270       28342 : TEST(ExternalInternalizedStringCollectedAtGC) {
   19271           5 :   int destroyed = 0;
   19272           5 :   { LocalContext env;
   19273          10 :     v8::HandleScope handle_scope(env->GetIsolate());
   19274             :     CompileRun("var ring = 'One string to test them all';");
   19275             :     const char* s = "One string to test them all";
   19276             :     TestOneByteResource* inscription =
   19277           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   19278             :     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
   19279          10 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   19280           5 :     ring->MakeExternal(inscription);
   19281             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   19282           5 :     CHECK_EQ(0, destroyed);
   19283           5 :     USE(ring);
   19284             :   }
   19285             : 
   19286             :   // Garbage collector deals swift blows to evil.
   19287           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
   19288           5 :   CcTest::CollectAllAvailableGarbage();
   19289             : 
   19290             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   19291           5 :   CHECK_EQ(1, destroyed);
   19292           5 : }
   19293             : 
   19294             : 
   19295             : static double DoubleFromBits(uint64_t value) {
   19296             :   double target;
   19297             :   i::MemCopy(&target, &value, sizeof(target));
   19298             :   return target;
   19299             : }
   19300             : 
   19301             : 
   19302             : static uint64_t DoubleToBits(double value) {
   19303             :   uint64_t target;
   19304             :   i::MemCopy(&target, &value, sizeof(target));
   19305             :   return target;
   19306             : }
   19307             : 
   19308             : 
   19309         120 : static double DoubleToDateTime(double input) {
   19310             :   double date_limit = 864e13;
   19311         120 :   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   19312             :     return std::numeric_limits<double>::quiet_NaN();
   19313             :   }
   19314          60 :   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   19315             : }
   19316             : 
   19317             : 
   19318             : // We don't have a consistent way to write 64-bit constants syntactically, so we
   19319             : // split them into two 32-bit constants and combine them programmatically.
   19320             : static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   19321             :   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   19322             : }
   19323             : 
   19324             : 
   19325       28343 : THREADED_TEST(QuietSignalingNaNs) {
   19326           6 :   LocalContext context;
   19327           6 :   v8::Isolate* isolate = context->GetIsolate();
   19328          12 :   v8::HandleScope scope(isolate);
   19329          12 :   v8::TryCatch try_catch(isolate);
   19330             : 
   19331             :   // Special double values.
   19332             :   double snan = DoubleFromBits(0x7FF00000, 0x00000001);
   19333             :   double qnan = DoubleFromBits(0x7FF80000, 0x00000000);
   19334             :   double infinity = DoubleFromBits(0x7FF00000, 0x00000000);
   19335             :   double max_normal = DoubleFromBits(0x7FEFFFFF, 0xFFFFFFFFu);
   19336             :   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   19337             :   double max_denormal = DoubleFromBits(0x000FFFFF, 0xFFFFFFFFu);
   19338             :   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   19339             : 
   19340             :   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   19341             :   // on either side of the epoch.
   19342             :   double date_limit = 864e13;
   19343             : 
   19344             :   double test_values[] = {
   19345             :       snan,
   19346             :       qnan,
   19347             :       infinity,
   19348             :       max_normal,
   19349             :       date_limit + 1,
   19350             :       date_limit,
   19351             :       min_normal,
   19352             :       max_denormal,
   19353             :       min_denormal,
   19354             :       0,
   19355             :       -0,
   19356             :       -min_denormal,
   19357             :       -max_denormal,
   19358             :       -min_normal,
   19359             :       -date_limit,
   19360             :       -date_limit - 1,
   19361             :       -max_normal,
   19362             :       -infinity,
   19363             :       -qnan,
   19364             :       -snan
   19365           6 :   };
   19366             :   int num_test_values = 20;
   19367             : 
   19368         126 :   for (int i = 0; i < num_test_values; i++) {
   19369         120 :     double test_value = test_values[i];
   19370             : 
   19371             :     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   19372         120 :     v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
   19373         240 :     double stored_number = number->NumberValue(context.local()).FromJust();
   19374         120 :     if (!std::isnan(test_value)) {
   19375          96 :       CHECK_EQ(test_value, stored_number);
   19376             :     } else {
   19377             :       uint64_t stored_bits = DoubleToBits(stored_number);
   19378             :       // Check if quiet nan (bits 51..62 all set).
   19379             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   19380             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   19381             :     !defined(USE_SIMULATOR)
   19382             :       // Most significant fraction bit for quiet nan is set to 0
   19383             :       // on MIPS architecture. Allowed by IEEE-754.
   19384             :       CHECK_EQ(0xFFE, static_cast<int>((stored_bits >> 51) & 0xFFF));
   19385             : #else
   19386          24 :       CHECK_EQ(0xFFF, static_cast<int>((stored_bits >> 51) & 0xFFF));
   19387             : #endif
   19388             :     }
   19389             : 
   19390             :     // Check that Date::New preserves non-NaNs in the date range and
   19391             :     // quiets SNaNs.
   19392             :     v8::Local<v8::Value> date =
   19393         120 :         v8::Date::New(context.local(), test_value).ToLocalChecked();
   19394         120 :     double expected_stored_date = DoubleToDateTime(test_value);
   19395         240 :     double stored_date = date->NumberValue(context.local()).FromJust();
   19396         120 :     if (!std::isnan(expected_stored_date)) {
   19397          60 :       CHECK_EQ(expected_stored_date, stored_date);
   19398             :     } else {
   19399             :       uint64_t stored_bits = DoubleToBits(stored_date);
   19400             :       // Check if quiet nan (bits 51..62 all set).
   19401             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   19402             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   19403             :     !defined(USE_SIMULATOR)
   19404             :       // Most significant fraction bit for quiet nan is set to 0
   19405             :       // on MIPS architecture. Allowed by IEEE-754.
   19406             :       CHECK_EQ(0xFFE, static_cast<int>((stored_bits >> 51) & 0xFFF));
   19407             : #else
   19408          60 :       CHECK_EQ(0xFFF, static_cast<int>((stored_bits >> 51) & 0xFFF));
   19409             : #endif
   19410             :     }
   19411           6 :   }
   19412           6 : }
   19413             : 
   19414             : 
   19415          66 : static void SpaghettiIncident(
   19416         198 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   19417          66 :   v8::HandleScope scope(args.GetIsolate());
   19418         132 :   v8::TryCatch tc(args.GetIsolate());
   19419             :   v8::MaybeLocal<v8::String> str(
   19420         132 :       args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
   19421             :   USE(str);
   19422          66 :   if (tc.HasCaught())
   19423         132 :     tc.ReThrow();
   19424          66 : }
   19425             : 
   19426             : 
   19427             : // Test that an exception can be propagated down through a spaghetti
   19428             : // stack using ReThrow.
   19429       28343 : THREADED_TEST(SpaghettiStackReThrow) {
   19430           6 :   v8::Isolate* isolate = CcTest::isolate();
   19431           6 :   v8::HandleScope scope(isolate);
   19432          12 :   LocalContext context;
   19433             :   context->Global()
   19434             :       ->Set(context.local(), v8_str("s"),
   19435           6 :             v8::FunctionTemplate::New(isolate, SpaghettiIncident)
   19436          18 :                 ->GetFunction(context.local())
   19437          30 :                 .ToLocalChecked())
   19438          12 :       .FromJust();
   19439          12 :   v8::TryCatch try_catch(isolate);
   19440             :   CompileRun(
   19441             :       "var i = 0;"
   19442             :       "var o = {"
   19443             :       "  toString: function () {"
   19444             :       "    if (i == 10) {"
   19445             :       "      throw 'Hey!';"
   19446             :       "    } else {"
   19447             :       "      i++;"
   19448             :       "      return s(o);"
   19449             :       "    }"
   19450             :       "  }"
   19451             :       "};"
   19452             :       "s(o);");
   19453           6 :   CHECK(try_catch.HasCaught());
   19454          12 :   v8::String::Utf8Value value(isolate, try_catch.Exception());
   19455          12 :   CHECK_EQ(0, strcmp(*value, "Hey!"));
   19456           6 : }
   19457             : 
   19458             : 
   19459       28342 : TEST(Regress528) {
   19460             :   ManualGCScope manual_gc_scope;
   19461           5 :   v8::V8::Initialize();
   19462           5 :   v8::Isolate* isolate = CcTest::isolate();
   19463           5 :   i::FLAG_retain_maps_for_n_gc = 0;
   19464          10 :   v8::HandleScope scope(isolate);
   19465             :   v8::Local<Context> other_context;
   19466             :   int gc_count;
   19467             : 
   19468             :   // Create a context used to keep the code from aging in the compilation
   19469             :   // cache.
   19470           5 :   other_context = Context::New(isolate);
   19471             : 
   19472             :   // Context-dependent context data creates reference from the compilation
   19473             :   // cache to the global object.
   19474             :   const char* source_simple = "1";
   19475             :   {
   19476           5 :     v8::HandleScope scope(isolate);
   19477           5 :     v8::Local<Context> context = Context::New(isolate);
   19478             : 
   19479           5 :     context->Enter();
   19480           5 :     Local<v8::String> obj = v8_str("");
   19481           5 :     context->SetEmbedderData(0, obj);
   19482             :     CompileRun(source_simple);
   19483           5 :     context->Exit();
   19484             :   }
   19485           5 :   isolate->ContextDisposedNotification();
   19486           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   19487           5 :     other_context->Enter();
   19488             :     CompileRun(source_simple);
   19489           5 :     other_context->Exit();
   19490           5 :     CcTest::CollectAllGarbage();
   19491           5 :     if (GetGlobalObjectsCount() == 1) break;
   19492             :   }
   19493           5 :   CHECK_GE(2, gc_count);
   19494           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   19495             : 
   19496             :   // Eval in a function creates reference from the compilation cache to the
   19497             :   // global object.
   19498             :   const char* source_eval = "function f(){eval('1')}; f()";
   19499             :   {
   19500           5 :     v8::HandleScope scope(isolate);
   19501           5 :     v8::Local<Context> context = Context::New(isolate);
   19502             : 
   19503           5 :     context->Enter();
   19504             :     CompileRun(source_eval);
   19505           5 :     context->Exit();
   19506             :   }
   19507           5 :   isolate->ContextDisposedNotification();
   19508           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   19509           5 :     other_context->Enter();
   19510             :     CompileRun(source_eval);
   19511           5 :     other_context->Exit();
   19512           5 :     CcTest::CollectAllGarbage();
   19513           5 :     if (GetGlobalObjectsCount() == 1) break;
   19514             :   }
   19515           5 :   CHECK_GE(2, gc_count);
   19516           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   19517             : 
   19518             :   // Looking up the line number for an exception creates reference from the
   19519             :   // compilation cache to the global object.
   19520             :   const char* source_exception = "function f(){throw 1;} f()";
   19521             :   {
   19522           5 :     v8::HandleScope scope(isolate);
   19523           5 :     v8::Local<Context> context = Context::New(isolate);
   19524             : 
   19525           5 :     context->Enter();
   19526          10 :     v8::TryCatch try_catch(isolate);
   19527             :     CompileRun(source_exception);
   19528           5 :     CHECK(try_catch.HasCaught());
   19529           5 :     v8::Local<v8::Message> message = try_catch.Message();
   19530           5 :     CHECK(!message.IsEmpty());
   19531          10 :     CHECK_EQ(1, message->GetLineNumber(context).FromJust());
   19532          10 :     context->Exit();
   19533             :   }
   19534           5 :   isolate->ContextDisposedNotification();
   19535           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   19536           5 :     other_context->Enter();
   19537             :     CompileRun(source_exception);
   19538           5 :     other_context->Exit();
   19539           5 :     CcTest::CollectAllGarbage();
   19540           5 :     if (GetGlobalObjectsCount() == 1) break;
   19541             :   }
   19542           5 :   CHECK_GE(2, gc_count);
   19543           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   19544             : 
   19545           5 :   isolate->ContextDisposedNotification();
   19546           5 : }
   19547             : 
   19548             : 
   19549       28343 : THREADED_TEST(ScriptOrigin) {
   19550           6 :   LocalContext env;
   19551           6 :   v8::Isolate* isolate = env->GetIsolate();
   19552          12 :   v8::HandleScope scope(isolate);
   19553           6 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 1));
   19554           6 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   19555           6 :   array->Set(isolate, 0, symbol);
   19556             : 
   19557             :   v8::ScriptOrigin origin = v8::ScriptOrigin(
   19558             :       v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
   19559             :       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
   19560             :       v8::Local<v8::Integer>(), v8_str("http://sourceMapUrl"),
   19561             :       v8::True(env->GetIsolate()), v8::False(env->GetIsolate()),
   19562          42 :       v8::False(env->GetIsolate()), array);
   19563           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   19564           6 :   v8::Script::Compile(env.local(), script, &origin)
   19565           6 :       .ToLocalChecked()
   19566           6 :       ->Run(env.local())
   19567           6 :       .ToLocalChecked();
   19568             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19569          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19570             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19571          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19572             : 
   19573           6 :   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   19574           6 :   CHECK_EQ(0, strcmp("test",
   19575             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19576             :                                             script_origin_f.ResourceName())));
   19577          12 :   CHECK_EQ(
   19578             :       1,
   19579             :       script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   19580           6 :   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
   19581           6 :   CHECK(script_origin_f.Options().IsOpaque());
   19582           6 :   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
   19583          12 :   CHECK(script_origin_f.HostDefinedOptions()->Get(isolate, 0)->IsSymbol());
   19584             : 
   19585           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   19586             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19587             :                                             script_origin_f.SourceMapUrl())));
   19588             : 
   19589           6 :   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   19590           6 :   CHECK_EQ(0, strcmp("test",
   19591             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19592             :                                             script_origin_g.ResourceName())));
   19593          12 :   CHECK_EQ(
   19594             :       1,
   19595             :       script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   19596           6 :   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
   19597           6 :   CHECK(script_origin_g.Options().IsOpaque());
   19598           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   19599             :                      *v8::String::Utf8Value(env->GetIsolate(),
   19600             :                                             script_origin_g.SourceMapUrl())));
   19601          18 :   CHECK(script_origin_g.HostDefinedOptions()->Get(isolate, 0)->IsSymbol());
   19602           6 : }
   19603             : 
   19604             : 
   19605       28343 : THREADED_TEST(FunctionGetInferredName) {
   19606           6 :   LocalContext env;
   19607          12 :   v8::HandleScope scope(env->GetIsolate());
   19608           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19609             :   v8::Local<v8::String> script =
   19610           6 :       v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   19611           6 :   v8::Script::Compile(env.local(), script, &origin)
   19612           6 :       .ToLocalChecked()
   19613           6 :       ->Run(env.local())
   19614           6 :       .ToLocalChecked();
   19615             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19616          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19617          12 :   CHECK_EQ(0,
   19618             :            strcmp("foo.bar.baz", *v8::String::Utf8Value(env->GetIsolate(),
   19619           6 :                                                         f->GetInferredName())));
   19620           6 : }
   19621             : 
   19622             : 
   19623       28343 : THREADED_TEST(FunctionGetDebugName) {
   19624           6 :   LocalContext env;
   19625           6 :   v8::Isolate* isolate = env->GetIsolate();
   19626          12 :   v8::HandleScope scope(isolate);
   19627             :   const char* code =
   19628             :       "var error = false;"
   19629             :       "function a() { this.x = 1; };"
   19630             :       "a.displayName = 'display_a';"
   19631             :       "var b = (function() {"
   19632             :       "  var f = function() { this.x = 2; };"
   19633             :       "  f.displayName = 'display_b';"
   19634             :       "  return f;"
   19635             :       "})();"
   19636             :       "var c = function() {};"
   19637             :       "c.__defineGetter__('displayName', function() {"
   19638             :       "  error = true;"
   19639             :       "  throw new Error();"
   19640             :       "});"
   19641             :       "function d() {};"
   19642             :       "d.__defineGetter__('displayName', function() {"
   19643             :       "  error = true;"
   19644             :       "  return 'wrong_display_name';"
   19645             :       "});"
   19646             :       "function e() {};"
   19647             :       "e.displayName = 'wrong_display_name';"
   19648             :       "e.__defineSetter__('displayName', function() {"
   19649             :       "  error = true;"
   19650             :       "  throw new Error();"
   19651             :       "});"
   19652             :       "function f() {};"
   19653             :       "f.displayName = { 'foo': 6, toString: function() {"
   19654             :       "  error = true;"
   19655             :       "  return 'wrong_display_name';"
   19656             :       "}};"
   19657             :       "var g = function() {"
   19658             :       "  arguments.callee.displayName = 'set_in_runtime';"
   19659             :       "}; g();"
   19660             :       "var h = function() {};"
   19661             :       "h.displayName = 'displayName';"
   19662             :       "Object.defineProperty(h, 'name', { value: 'function.name' });"
   19663             :       "var i = function() {};"
   19664             :       "i.displayName = 239;"
   19665             :       "Object.defineProperty(i, 'name', { value: 'function.name' });"
   19666             :       "var j = function() {};"
   19667             :       "Object.defineProperty(j, 'name', { value: 'function.name' });"
   19668             :       "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
   19669             :       "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
   19670           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19671           6 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19672           6 :       .ToLocalChecked()
   19673           6 :       ->Run(env.local())
   19674           6 :       .ToLocalChecked();
   19675             :   v8::Local<v8::Value> error =
   19676          30 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19677           6 :   CHECK(!error->BooleanValue(isolate));
   19678             :   const char* functions[] = {"a", "display_a",
   19679             :                              "b", "display_b",
   19680             :                              "c", "c",
   19681             :                              "d", "d",
   19682             :                              "e", "e",
   19683             :                              "f", "f",
   19684             :                              "g", "set_in_runtime",
   19685             :                              "h", "displayName",
   19686             :                              "i", "function.name",
   19687             :                              "j", "function.name",
   19688             :                              "k", "foo.bar.baz",
   19689           6 :                              "l", "baz"};
   19690          78 :   for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
   19691             :     v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19692             :         env->Global()
   19693             :             ->Get(env.local(),
   19694          72 :                   v8::String::NewFromUtf8(isolate, functions[i * 2],
   19695          72 :                                           v8::NewStringType::kNormal)
   19696         288 :                       .ToLocalChecked())
   19697          72 :             .ToLocalChecked());
   19698          72 :     CHECK_EQ(0, strcmp(functions[i * 2 + 1],
   19699             :                        *v8::String::Utf8Value(isolate, f->GetDebugName())));
   19700           6 :   }
   19701           6 : }
   19702             : 
   19703             : 
   19704       28343 : THREADED_TEST(FunctionGetDisplayName) {
   19705           6 :   LocalContext env;
   19706           6 :   v8::Isolate* isolate = env->GetIsolate();
   19707          12 :   v8::HandleScope scope(isolate);
   19708             :   const char* code = "var error = false;"
   19709             :                      "function a() { this.x = 1; };"
   19710             :                      "a.displayName = 'display_a';"
   19711             :                      "var b = (function() {"
   19712             :                      "  var f = function() { this.x = 2; };"
   19713             :                      "  f.displayName = 'display_b';"
   19714             :                      "  return f;"
   19715             :                      "})();"
   19716             :                      "var c = function() {};"
   19717             :                      "c.__defineGetter__('displayName', function() {"
   19718             :                      "  error = true;"
   19719             :                      "  throw new Error();"
   19720             :                      "});"
   19721             :                      "function d() {};"
   19722             :                      "d.__defineGetter__('displayName', function() {"
   19723             :                      "  error = true;"
   19724             :                      "  return 'wrong_display_name';"
   19725             :                      "});"
   19726             :                      "function e() {};"
   19727             :                      "e.displayName = 'wrong_display_name';"
   19728             :                      "e.__defineSetter__('displayName', function() {"
   19729             :                      "  error = true;"
   19730             :                      "  throw new Error();"
   19731             :                      "});"
   19732             :                      "function f() {};"
   19733             :                      "f.displayName = { 'foo': 6, toString: function() {"
   19734             :                      "  error = true;"
   19735             :                      "  return 'wrong_display_name';"
   19736             :                      "}};"
   19737             :                      "var g = function() {"
   19738             :                      "  arguments.callee.displayName = 'set_in_runtime';"
   19739             :                      "}; g();";
   19740           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19741           6 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19742           6 :       .ToLocalChecked()
   19743           6 :       ->Run(env.local())
   19744           6 :       .ToLocalChecked();
   19745             :   v8::Local<v8::Value> error =
   19746          30 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19747             :   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   19748          30 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   19749             :   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   19750          30 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   19751             :   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   19752          30 :       env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
   19753             :   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   19754          30 :       env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
   19755             :   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   19756          30 :       env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
   19757             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19758          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19759             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19760          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19761           6 :   CHECK(!error->BooleanValue(isolate));
   19762           6 :   CHECK_EQ(0, strcmp("display_a",
   19763             :                      *v8::String::Utf8Value(isolate, a->GetDisplayName())));
   19764           6 :   CHECK_EQ(0, strcmp("display_b",
   19765             :                      *v8::String::Utf8Value(isolate, b->GetDisplayName())));
   19766          12 :   CHECK(c->GetDisplayName()->IsUndefined());
   19767          12 :   CHECK(d->GetDisplayName()->IsUndefined());
   19768          12 :   CHECK(e->GetDisplayName()->IsUndefined());
   19769          12 :   CHECK(f->GetDisplayName()->IsUndefined());
   19770           6 :   CHECK_EQ(0, strcmp("set_in_runtime",
   19771           6 :                      *v8::String::Utf8Value(isolate, g->GetDisplayName())));
   19772           6 : }
   19773             : 
   19774             : 
   19775       28343 : THREADED_TEST(ScriptLineNumber) {
   19776           6 :   LocalContext env;
   19777          12 :   v8::HandleScope scope(env->GetIsolate());
   19778           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19779           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   19780           6 :   v8::Script::Compile(env.local(), script, &origin)
   19781           6 :       .ToLocalChecked()
   19782           6 :       ->Run(env.local())
   19783           6 :       .ToLocalChecked();
   19784             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19785          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19786             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19787          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19788           6 :   CHECK_EQ(0, f->GetScriptLineNumber());
   19789          12 :   CHECK_EQ(2, g->GetScriptLineNumber());
   19790           6 : }
   19791             : 
   19792             : 
   19793       28343 : THREADED_TEST(ScriptColumnNumber) {
   19794           6 :   LocalContext env;
   19795           6 :   v8::Isolate* isolate = env->GetIsolate();
   19796          12 :   v8::HandleScope scope(isolate);
   19797             :   v8::ScriptOrigin origin =
   19798             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19799           6 :                        v8::Integer::New(isolate, 2));
   19800             :   v8::Local<v8::String> script =
   19801           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19802           6 :   v8::Script::Compile(env.local(), script, &origin)
   19803           6 :       .ToLocalChecked()
   19804           6 :       ->Run(env.local())
   19805           6 :       .ToLocalChecked();
   19806             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19807          30 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19808             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19809          30 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19810           6 :   CHECK_EQ(14, foo->GetScriptColumnNumber());
   19811          12 :   CHECK_EQ(17, bar->GetScriptColumnNumber());
   19812           6 : }
   19813             : 
   19814             : 
   19815       28343 : THREADED_TEST(FunctionGetScriptId) {
   19816           6 :   LocalContext env;
   19817           6 :   v8::Isolate* isolate = env->GetIsolate();
   19818          12 :   v8::HandleScope scope(isolate);
   19819             :   v8::ScriptOrigin origin =
   19820             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19821           6 :                        v8::Integer::New(isolate, 2));
   19822             :   v8::Local<v8::String> scriptSource =
   19823           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19824             :   v8::Local<v8::Script> script(
   19825           6 :       v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
   19826           6 :   script->Run(env.local()).ToLocalChecked();
   19827             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19828          30 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19829             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19830          30 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19831          12 :   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   19832          18 :   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   19833           6 : }
   19834             : 
   19835             : 
   19836       28343 : THREADED_TEST(FunctionGetBoundFunction) {
   19837           6 :   LocalContext env;
   19838          12 :   v8::HandleScope scope(env->GetIsolate());
   19839           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19840             :   v8::Local<v8::String> script = v8_str(
   19841             :       "var a = new Object();\n"
   19842             :       "a.x = 1;\n"
   19843             :       "function f () { return this.x };\n"
   19844             :       "var g = f.bind(a);\n"
   19845           6 :       "var b = g();");
   19846           6 :   v8::Script::Compile(env.local(), script, &origin)
   19847           6 :       .ToLocalChecked()
   19848           6 :       ->Run(env.local())
   19849           6 :       .ToLocalChecked();
   19850             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19851          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19852             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19853          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19854          12 :   CHECK(g->GetBoundFunction()->IsFunction());
   19855             :   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   19856           6 :       g->GetBoundFunction());
   19857          18 :   CHECK(f->GetName()
   19858             :             ->Equals(env.local(), original_function->GetName())
   19859             :             .FromJust());
   19860           6 :   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   19861           6 :   CHECK_EQ(f->GetScriptColumnNumber(),
   19862           6 :            original_function->GetScriptColumnNumber());
   19863           6 : }
   19864             : 
   19865             : 
   19866         330 : static void GetterWhichReturns42(
   19867             :     Local<String> name,
   19868             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19869         660 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19870         660 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19871         330 :   info.GetReturnValue().Set(v8_num(42));
   19872         330 : }
   19873             : 
   19874             : 
   19875         270 : static void SetterWhichSetsYOnThisTo23(
   19876             :     Local<String> name,
   19877             :     Local<Value> value,
   19878             :     const v8::PropertyCallbackInfo<void>& info) {
   19879         540 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19880         540 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19881             :   Local<Object>::Cast(info.This())
   19882         810 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19883         540 :       .FromJust();
   19884         270 : }
   19885             : 
   19886             : 
   19887         120 : void FooGetInterceptor(Local<Name> name,
   19888             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19889         240 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19890         240 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19891         360 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19892         240 :            .FromJust()) {
   19893         120 :     return;
   19894             :   }
   19895          96 :   info.GetReturnValue().Set(v8_num(42));
   19896             : }
   19897             : 
   19898             : 
   19899         336 : void FooSetInterceptor(Local<Name> name, Local<Value> value,
   19900             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19901         672 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19902         672 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19903        1008 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19904         672 :            .FromJust()) {
   19905         336 :     return;
   19906             :   }
   19907             :   Local<Object>::Cast(info.This())
   19908         288 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19909         192 :       .FromJust();
   19910          96 :   info.GetReturnValue().Set(v8_num(23));
   19911             : }
   19912             : 
   19913             : 
   19914       28342 : TEST(SetterOnConstructorPrototype) {
   19915           5 :   v8::Isolate* isolate = CcTest::isolate();
   19916           5 :   v8::HandleScope scope(isolate);
   19917           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19918             :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19919           5 :                      SetterWhichSetsYOnThisTo23);
   19920          10 :   LocalContext context;
   19921          30 :   CHECK(context->Global()
   19922             :             ->Set(context.local(), v8_str("P"),
   19923             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19924             :             .FromJust());
   19925             :   CompileRun("function C1() {"
   19926             :              "  this.x = 23;"
   19927             :              "};"
   19928             :              "C1.prototype = P;"
   19929             :              "function C2() {"
   19930             :              "  this.x = 23"
   19931             :              "};"
   19932             :              "C2.prototype = { };"
   19933             :              "C2.prototype.__proto__ = P;");
   19934             : 
   19935             :   v8::Local<v8::Script> script;
   19936             :   script = v8_compile("new C1();");
   19937          55 :   for (int i = 0; i < 10; i++) {
   19938             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19939          50 :         script->Run(context.local()).ToLocalChecked());
   19940         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19941             :                      .ToLocalChecked()
   19942             :                      ->Int32Value(context.local())
   19943             :                      .FromJust());
   19944         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19945             :                      .ToLocalChecked()
   19946             :                      ->Int32Value(context.local())
   19947             :                      .FromJust());
   19948             :   }
   19949             : 
   19950             :   script = v8_compile("new C2();");
   19951          55 :   for (int i = 0; i < 10; i++) {
   19952             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19953          50 :         script->Run(context.local()).ToLocalChecked());
   19954         200 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
   19955             :                      .ToLocalChecked()
   19956             :                      ->Int32Value(context.local())
   19957             :                      .FromJust());
   19958         200 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
   19959             :                      .ToLocalChecked()
   19960             :                      ->Int32Value(context.local())
   19961             :                      .FromJust());
   19962           5 :   }
   19963           5 : }
   19964             : 
   19965             : 
   19966           0 : static void NamedPropertySetterWhichSetsYOnThisTo23(
   19967             :     Local<Name> name, Local<Value> value,
   19968             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19969           0 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
   19970           0 :           .FromJust()) {
   19971             :     Local<Object>::Cast(info.This())
   19972           0 :         ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19973           0 :         .FromJust();
   19974             :   }
   19975           0 : }
   19976             : 
   19977             : 
   19978       28343 : THREADED_TEST(InterceptorOnConstructorPrototype) {
   19979           6 :   v8::Isolate* isolate = CcTest::isolate();
   19980           6 :   v8::HandleScope scope(isolate);
   19981           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19982             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19983             :       NamedPropertyGetterWhichReturns42,
   19984           6 :       NamedPropertySetterWhichSetsYOnThisTo23));
   19985          12 :   LocalContext context;
   19986          36 :   CHECK(context->Global()
   19987             :             ->Set(context.local(), v8_str("P"),
   19988             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19989             :             .FromJust());
   19990             :   CompileRun("function C1() {"
   19991             :              "  this.x = 23;"
   19992             :              "};"
   19993             :              "C1.prototype = P;"
   19994             :              "function C2() {"
   19995             :              "  this.x = 23"
   19996             :              "};"
   19997             :              "C2.prototype = { };"
   19998             :              "C2.prototype.__proto__ = P;");
   19999             : 
   20000             :   v8::Local<v8::Script> script;
   20001             :   script = v8_compile("new C1();");
   20002          66 :   for (int i = 0; i < 10; i++) {
   20003             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   20004          60 :         script->Run(context.local()).ToLocalChecked());
   20005         240 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   20006             :                      .ToLocalChecked()
   20007             :                      ->Int32Value(context.local())
   20008             :                      .FromJust());
   20009         240 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   20010             :                      .ToLocalChecked()
   20011             :                      ->Int32Value(context.local())
   20012             :                      .FromJust());
   20013             :   }
   20014             : 
   20015             :   script = v8_compile("new C2();");
   20016          66 :   for (int i = 0; i < 10; i++) {
   20017             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   20018          60 :         script->Run(context.local()).ToLocalChecked());
   20019         240 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
   20020             :                      .ToLocalChecked()
   20021             :                      ->Int32Value(context.local())
   20022             :                      .FromJust());
   20023         240 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
   20024             :                      .ToLocalChecked()
   20025             :                      ->Int32Value(context.local())
   20026             :                      .FromJust());
   20027           6 :   }
   20028           6 : }
   20029             : 
   20030             : 
   20031       28342 : TEST(Regress618) {
   20032             :   const char* source = "function C1() {"
   20033             :                        "  this.x = 23;"
   20034             :                        "};"
   20035             :                        "C1.prototype = P;";
   20036             : 
   20037           5 :   LocalContext context;
   20038           5 :   v8::Isolate* isolate = context->GetIsolate();
   20039          10 :   v8::HandleScope scope(isolate);
   20040             :   v8::Local<v8::Script> script;
   20041             : 
   20042             :   // Use a simple object as prototype.
   20043           5 :   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   20044          20 :   prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
   20045          25 :   CHECK(context->Global()
   20046             :             ->Set(context.local(), v8_str("P"), prototype)
   20047             :             .FromJust());
   20048             : 
   20049             :   // This compile will add the code to the compilation cache.
   20050             :   CompileRun(source);
   20051             : 
   20052             :   script = v8_compile("new C1();");
   20053             :   // Allow enough iterations for the inobject slack tracking logic
   20054             :   // to finalize instance size and install the fast construct stub.
   20055        1285 :   for (int i = 0; i < 256; i++) {
   20056             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   20057        1280 :         script->Run(context.local()).ToLocalChecked());
   20058        5120 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   20059             :                      .ToLocalChecked()
   20060             :                      ->Int32Value(context.local())
   20061             :                      .FromJust());
   20062        5120 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   20063             :                      .ToLocalChecked()
   20064             :                      ->Int32Value(context.local())
   20065             :                      .FromJust());
   20066             :   }
   20067             : 
   20068             :   // Use an API object with accessors as prototype.
   20069           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20070             :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   20071           5 :                      SetterWhichSetsYOnThisTo23);
   20072          30 :   CHECK(context->Global()
   20073             :             ->Set(context.local(), v8_str("P"),
   20074             :                   templ->NewInstance(context.local()).ToLocalChecked())
   20075             :             .FromJust());
   20076             : 
   20077             :   // This compile will get the code from the compilation cache.
   20078             :   CompileRun(source);
   20079             : 
   20080             :   script = v8_compile("new C1();");
   20081          55 :   for (int i = 0; i < 10; i++) {
   20082             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   20083          50 :         script->Run(context.local()).ToLocalChecked());
   20084         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   20085             :                      .ToLocalChecked()
   20086             :                      ->Int32Value(context.local())
   20087             :                      .FromJust());
   20088         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   20089             :                      .ToLocalChecked()
   20090             :                      ->Int32Value(context.local())
   20091             :                      .FromJust());
   20092           5 :   }
   20093           5 : }
   20094             : 
   20095             : v8::Isolate* gc_callbacks_isolate = nullptr;
   20096             : int prologue_call_count = 0;
   20097             : int epilogue_call_count = 0;
   20098             : int prologue_call_count_second = 0;
   20099             : int epilogue_call_count_second = 0;
   20100             : int prologue_call_count_alloc = 0;
   20101             : int epilogue_call_count_alloc = 0;
   20102             : 
   20103          20 : void PrologueCallback(v8::Isolate* isolate,
   20104             :                       v8::GCType,
   20105             :                       v8::GCCallbackFlags flags) {
   20106          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20107          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20108          20 :   ++prologue_call_count;
   20109          20 : }
   20110             : 
   20111          20 : void EpilogueCallback(v8::Isolate* isolate,
   20112             :                       v8::GCType,
   20113             :                       v8::GCCallbackFlags flags) {
   20114          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20115          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20116          20 :   ++epilogue_call_count;
   20117          20 : }
   20118             : 
   20119             : 
   20120          20 : void PrologueCallbackSecond(v8::Isolate* isolate,
   20121             :                             v8::GCType,
   20122             :                             v8::GCCallbackFlags flags) {
   20123          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20124          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20125          20 :   ++prologue_call_count_second;
   20126          20 : }
   20127             : 
   20128             : 
   20129          20 : void EpilogueCallbackSecond(v8::Isolate* isolate,
   20130             :                             v8::GCType,
   20131             :                             v8::GCCallbackFlags flags) {
   20132          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20133          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20134          20 :   ++epilogue_call_count_second;
   20135          20 : }
   20136             : 
   20137          20 : void PrologueCallbackNew(v8::Isolate* isolate, v8::GCType,
   20138             :                          v8::GCCallbackFlags flags, void* data) {
   20139          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20140          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20141          20 :   ++*static_cast<int*>(data);
   20142          20 : }
   20143             : 
   20144          20 : void EpilogueCallbackNew(v8::Isolate* isolate, v8::GCType,
   20145             :                          v8::GCCallbackFlags flags, void* data) {
   20146          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20147          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20148          20 :   ++*static_cast<int*>(data);
   20149          20 : }
   20150             : 
   20151           5 : void PrologueCallbackAlloc(v8::Isolate* isolate,
   20152             :                            v8::GCType,
   20153             :                            v8::GCCallbackFlags flags) {
   20154           5 :   v8::HandleScope scope(isolate);
   20155             : 
   20156           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20157           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20158           5 :   ++prologue_call_count_alloc;
   20159             : 
   20160             :   // Simulate full heap to see if we will reenter this callback
   20161           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   20162             : 
   20163           5 :   Local<Object> obj = Object::New(isolate);
   20164           5 :   CHECK(!obj.IsEmpty());
   20165             : 
   20166           5 :   CcTest::PreciseCollectAllGarbage();
   20167           5 : }
   20168             : 
   20169             : 
   20170           5 : void EpilogueCallbackAlloc(v8::Isolate* isolate,
   20171             :                            v8::GCType,
   20172             :                            v8::GCCallbackFlags flags) {
   20173           5 :   v8::HandleScope scope(isolate);
   20174             : 
   20175           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   20176           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   20177           5 :   ++epilogue_call_count_alloc;
   20178             : 
   20179             :   // Simulate full heap to see if we will reenter this callback
   20180           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   20181             : 
   20182           5 :   Local<Object> obj = Object::New(isolate);
   20183           5 :   CHECK(!obj.IsEmpty());
   20184             : 
   20185           5 :   CcTest::PreciseCollectAllGarbage();
   20186           5 : }
   20187             : 
   20188             : 
   20189       28342 : TEST(GCCallbacksOld) {
   20190           5 :   LocalContext context;
   20191             : 
   20192           5 :   gc_callbacks_isolate = context->GetIsolate();
   20193             : 
   20194           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
   20195           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
   20196           5 :   CHECK_EQ(0, prologue_call_count);
   20197           5 :   CHECK_EQ(0, epilogue_call_count);
   20198           5 :   CcTest::CollectAllGarbage();
   20199           5 :   CHECK_EQ(1, prologue_call_count);
   20200           5 :   CHECK_EQ(1, epilogue_call_count);
   20201           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
   20202           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
   20203           5 :   CcTest::CollectAllGarbage();
   20204           5 :   CHECK_EQ(2, prologue_call_count);
   20205           5 :   CHECK_EQ(2, epilogue_call_count);
   20206           5 :   CHECK_EQ(1, prologue_call_count_second);
   20207           5 :   CHECK_EQ(1, epilogue_call_count_second);
   20208           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
   20209           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
   20210           5 :   CcTest::CollectAllGarbage();
   20211           5 :   CHECK_EQ(2, prologue_call_count);
   20212           5 :   CHECK_EQ(2, epilogue_call_count);
   20213           5 :   CHECK_EQ(2, prologue_call_count_second);
   20214           5 :   CHECK_EQ(2, epilogue_call_count_second);
   20215           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
   20216           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   20217           5 :   CcTest::CollectAllGarbage();
   20218           5 :   CHECK_EQ(2, prologue_call_count);
   20219           5 :   CHECK_EQ(2, epilogue_call_count);
   20220           5 :   CHECK_EQ(2, prologue_call_count_second);
   20221           5 :   CHECK_EQ(2, epilogue_call_count_second);
   20222           5 : }
   20223             : 
   20224       28342 : TEST(GCCallbacksWithData) {
   20225           5 :   LocalContext context;
   20226             : 
   20227           5 :   gc_callbacks_isolate = context->GetIsolate();
   20228           5 :   int prologue1 = 0;
   20229           5 :   int epilogue1 = 0;
   20230           5 :   int prologue2 = 0;
   20231           5 :   int epilogue2 = 0;
   20232             : 
   20233           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue1);
   20234           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue1);
   20235           5 :   CHECK_EQ(0, prologue1);
   20236           5 :   CHECK_EQ(0, epilogue1);
   20237           5 :   CHECK_EQ(0, prologue2);
   20238           5 :   CHECK_EQ(0, epilogue2);
   20239           5 :   CcTest::CollectAllGarbage();
   20240           5 :   CHECK_EQ(1, prologue1);
   20241           5 :   CHECK_EQ(1, epilogue1);
   20242           5 :   CHECK_EQ(0, prologue2);
   20243           5 :   CHECK_EQ(0, epilogue2);
   20244           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue2);
   20245           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue2);
   20246           5 :   CcTest::CollectAllGarbage();
   20247           5 :   CHECK_EQ(2, prologue1);
   20248           5 :   CHECK_EQ(2, epilogue1);
   20249           5 :   CHECK_EQ(1, prologue2);
   20250           5 :   CHECK_EQ(1, epilogue2);
   20251             :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   20252           5 :                                                   &prologue1);
   20253             :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   20254           5 :                                                   &epilogue1);
   20255           5 :   CcTest::CollectAllGarbage();
   20256           5 :   CHECK_EQ(2, prologue1);
   20257           5 :   CHECK_EQ(2, epilogue1);
   20258           5 :   CHECK_EQ(2, prologue2);
   20259           5 :   CHECK_EQ(2, epilogue2);
   20260             :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   20261           5 :                                                   &prologue2);
   20262             :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   20263           5 :                                                   &epilogue2);
   20264           5 :   CcTest::CollectAllGarbage();
   20265           5 :   CHECK_EQ(2, prologue1);
   20266           5 :   CHECK_EQ(2, epilogue1);
   20267           5 :   CHECK_EQ(2, prologue2);
   20268           5 :   CHECK_EQ(2, epilogue2);
   20269           5 : }
   20270             : 
   20271       28342 : TEST(GCCallbacks) {
   20272           5 :   LocalContext context;
   20273           5 :   v8::Isolate* isolate = context->GetIsolate();
   20274           5 :   gc_callbacks_isolate = isolate;
   20275           5 :   isolate->AddGCPrologueCallback(PrologueCallback);
   20276           5 :   isolate->AddGCEpilogueCallback(EpilogueCallback);
   20277           5 :   CHECK_EQ(0, prologue_call_count);
   20278           5 :   CHECK_EQ(0, epilogue_call_count);
   20279           5 :   CcTest::CollectAllGarbage();
   20280           5 :   CHECK_EQ(1, prologue_call_count);
   20281           5 :   CHECK_EQ(1, epilogue_call_count);
   20282           5 :   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   20283           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   20284           5 :   CcTest::CollectAllGarbage();
   20285           5 :   CHECK_EQ(2, prologue_call_count);
   20286           5 :   CHECK_EQ(2, epilogue_call_count);
   20287           5 :   CHECK_EQ(1, prologue_call_count_second);
   20288           5 :   CHECK_EQ(1, epilogue_call_count_second);
   20289           5 :   isolate->RemoveGCPrologueCallback(PrologueCallback);
   20290           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   20291           5 :   CcTest::CollectAllGarbage();
   20292           5 :   CHECK_EQ(2, prologue_call_count);
   20293           5 :   CHECK_EQ(2, epilogue_call_count);
   20294           5 :   CHECK_EQ(2, prologue_call_count_second);
   20295           5 :   CHECK_EQ(2, epilogue_call_count_second);
   20296           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   20297           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   20298           5 :   CcTest::CollectAllGarbage();
   20299           5 :   CHECK_EQ(2, prologue_call_count);
   20300           5 :   CHECK_EQ(2, epilogue_call_count);
   20301           5 :   CHECK_EQ(2, prologue_call_count_second);
   20302           5 :   CHECK_EQ(2, epilogue_call_count_second);
   20303             : 
   20304           5 :   CHECK_EQ(0, prologue_call_count_alloc);
   20305           5 :   CHECK_EQ(0, epilogue_call_count_alloc);
   20306           5 :   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   20307           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   20308           5 :   CcTest::PreciseCollectAllGarbage();
   20309           5 :   CHECK_EQ(1, prologue_call_count_alloc);
   20310           5 :   CHECK_EQ(1, epilogue_call_count_alloc);
   20311           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   20312           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   20313           5 : }
   20314             : 
   20315             : 
   20316       28343 : THREADED_TEST(TwoByteStringInOneByteCons) {
   20317             :   // See Chromium issue 47824.
   20318           6 :   LocalContext context;
   20319          12 :   v8::HandleScope scope(context->GetIsolate());
   20320             : 
   20321             :   const char* init_code =
   20322             :       "var str1 = 'abelspendabel';"
   20323             :       "var str2 = str1 + str1 + str1;"
   20324             :       "str2;";
   20325             :   Local<Value> result = CompileRun(init_code);
   20326             : 
   20327           6 :   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   20328           6 :   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   20329             : 
   20330           6 :   CHECK(result->IsString());
   20331             :   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   20332             :   int length = string->length();
   20333           6 :   CHECK(string->IsOneByteRepresentation());
   20334             : 
   20335           6 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
   20336           6 :   i::Handle<i::String> flat_string = i::String::Flatten(i_isolate, string);
   20337             : 
   20338           6 :   CHECK(string->IsOneByteRepresentation());
   20339           6 :   CHECK(flat_string->IsOneByteRepresentation());
   20340             : 
   20341             :   // Create external resource.
   20342           6 :   uint16_t* uc16_buffer = new uint16_t[length + 1];
   20343             : 
   20344           6 :   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   20345           6 :   uc16_buffer[length] = 0;
   20346             : 
   20347           6 :   TestResource resource(uc16_buffer);
   20348             : 
   20349           6 :   flat_string->MakeExternal(&resource);
   20350             : 
   20351           6 :   CHECK(flat_string->IsTwoByteRepresentation());
   20352             : 
   20353             :   // If the cons string has been short-circuited, skip the following checks.
   20354           6 :   if (!string.is_identical_to(flat_string)) {
   20355             :     // At this point, we should have a Cons string which is flat and one-byte,
   20356             :     // with a first half that is a two-byte string (although it only contains
   20357             :     // one-byte characters). This is a valid sequence of steps, and it can
   20358             :     // happen in real pages.
   20359           6 :     CHECK(string->IsOneByteRepresentation());
   20360           6 :     i::ConsString cons = i::ConsString::cast(*string);
   20361          12 :     CHECK_EQ(0, cons->second()->length());
   20362           6 :     CHECK(cons->first()->IsTwoByteRepresentation());
   20363             :   }
   20364             : 
   20365             :   // Check that some string operations work.
   20366             : 
   20367             :   // Atom RegExp.
   20368             :   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   20369          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   20370             : 
   20371             :   // Nonatom RegExp.
   20372             :   reresult = CompileRun("str2.match(/abe./g).length;");
   20373          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   20374             : 
   20375             :   reresult = CompileRun("str2.search(/bel/g);");
   20376          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   20377             : 
   20378             :   reresult = CompileRun("str2.search(/be./g);");
   20379          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   20380             : 
   20381             :   ExpectTrue("/bel/g.test(str2);");
   20382             : 
   20383             :   ExpectTrue("/be./g.test(str2);");
   20384             : 
   20385             :   reresult = CompileRun("/bel/g.exec(str2);");
   20386           6 :   CHECK(!reresult->IsNull());
   20387             : 
   20388             :   reresult = CompileRun("/be./g.exec(str2);");
   20389           6 :   CHECK(!reresult->IsNull());
   20390             : 
   20391           6 :   ExpectString("str2.substring(2, 10);", "elspenda");
   20392             : 
   20393           6 :   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   20394             : 
   20395           6 :   ExpectString("str2.charAt(2);", "e");
   20396             : 
   20397           6 :   ExpectObject("str2.indexOf('els');", indexof);
   20398             : 
   20399           6 :   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   20400             : 
   20401             :   reresult = CompileRun("str2.charCodeAt(2);");
   20402          12 :   CHECK_EQ(static_cast<int32_t>('e'),
   20403             :            reresult->Int32Value(context.local()).FromJust());
   20404             :   // This avoids the GC from trying to free stack allocated resources.
   20405             :   i::Handle<i::ExternalTwoByteString>::cast(flat_string)
   20406          18 :       ->SetResource(i_isolate, nullptr);
   20407           6 : }
   20408             : 
   20409             : 
   20410       28342 : TEST(ContainsOnlyOneByte) {
   20411           5 :   v8::V8::Initialize();
   20412           5 :   v8::Isolate* isolate = CcTest::isolate();
   20413           5 :   v8::HandleScope scope(isolate);
   20414             :   // Make a buffer long enough that it won't automatically be converted.
   20415             :   const int length = 512;
   20416             :   // Ensure word aligned assignment.
   20417             :   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   20418           5 :   std::unique_ptr<uintptr_t[]> aligned_contents(new uintptr_t[aligned_length]);
   20419             :   uint16_t* string_contents =
   20420             :       reinterpret_cast<uint16_t*>(aligned_contents.get());
   20421             :   // Set to contain only one byte.
   20422        2560 :   for (int i = 0; i < length-1; i++) {
   20423        2555 :     string_contents[i] = 0x41;
   20424             :   }
   20425           5 :   string_contents[length-1] = 0;
   20426             :   // Simple case.
   20427             :   Local<String> string =
   20428             :       String::NewExternalTwoByte(
   20429           5 :           isolate, new TestResource(string_contents, nullptr, false))
   20430           5 :           .ToLocalChecked();
   20431           5 :   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   20432             :   // Counter example.
   20433             :   string = String::NewFromTwoByte(isolate, string_contents,
   20434             :                                   v8::NewStringType::kNormal)
   20435           5 :                .ToLocalChecked();
   20436           5 :   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   20437             :   // Test left right and balanced cons strings.
   20438           5 :   Local<String> base = v8_str("a");
   20439           5 :   Local<String> left = base;
   20440           5 :   Local<String> right = base;
   20441        5005 :   for (int i = 0; i < 1000; i++) {
   20442        5000 :     left = String::Concat(isolate, base, left);
   20443        5000 :     right = String::Concat(isolate, right, base);
   20444             :   }
   20445           5 :   Local<String> balanced = String::Concat(isolate, left, base);
   20446           5 :   balanced = String::Concat(isolate, balanced, right);
   20447           5 :   Local<String> cons_strings[] = {left, balanced, right};
   20448             :   Local<String> two_byte =
   20449             :       String::NewExternalTwoByte(
   20450           5 :           isolate, new TestResource(string_contents, nullptr, false))
   20451          10 :           .ToLocalChecked();
   20452             :   USE(two_byte); USE(cons_strings);
   20453          20 :   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   20454             :     // Base assumptions.
   20455          15 :     string = cons_strings[i];
   20456          15 :     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   20457             :     // Test left and right concatentation.
   20458          15 :     string = String::Concat(isolate, two_byte, cons_strings[i]);
   20459          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   20460          15 :     string = String::Concat(isolate, cons_strings[i], two_byte);
   20461          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   20462             :   }
   20463             :   // Set bits in different positions
   20464             :   // for strings of different lengths and alignments.
   20465          35 :   for (int alignment = 0; alignment < 7; alignment++) {
   20466         280 :     for (int size = 2; alignment + size < length; size *= 2) {
   20467             :       int zero_offset = size + alignment;
   20468         280 :       string_contents[zero_offset] = 0;
   20469       18130 :       for (int i = 0; i < size; i++) {
   20470       17850 :         int shift = 8 + (i % 7);
   20471       17850 :         string_contents[alignment + i] = 1 << shift;
   20472             :         string = String::NewExternalTwoByte(
   20473             :                      isolate, new TestResource(string_contents + alignment,
   20474       17850 :                                                nullptr, false))
   20475       17850 :                      .ToLocalChecked();
   20476       17850 :         CHECK_EQ(size, string->Length());
   20477       17850 :         CHECK(!string->ContainsOnlyOneByte());
   20478       17850 :         string_contents[alignment + i] = 0x41;
   20479             :       }
   20480         280 :       string_contents[zero_offset] = 0x41;
   20481             :     }
   20482           5 :   }
   20483           5 : }
   20484             : 
   20485             : 
   20486             : // Failed access check callback that performs a GC on each invocation.
   20487          75 : void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   20488             :                                  v8::AccessType type,
   20489             :                                  Local<v8::Value> data) {
   20490          75 :   CcTest::CollectAllGarbage();
   20491             :   CcTest::isolate()->ThrowException(
   20492          75 :       v8::Exception::Error(v8_str("cross context")));
   20493          75 : }
   20494             : 
   20495             : 
   20496       28342 : TEST(GCInFailedAccessCheckCallback) {
   20497             :   // Install a failed access check callback that performs a GC on each
   20498             :   // invocation. Then force the callback to be called from va
   20499             : 
   20500           5 :   v8::V8::Initialize();
   20501           5 :   v8::Isolate* isolate = CcTest::isolate();
   20502             : 
   20503           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   20504             : 
   20505           5 :   v8::HandleScope scope(isolate);
   20506             : 
   20507             :   // Create an ObjectTemplate for global objects and install access
   20508             :   // check callbacks that will block access.
   20509             :   v8::Local<v8::ObjectTemplate> global_template =
   20510           5 :       v8::ObjectTemplate::New(isolate);
   20511           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   20512             : 
   20513             :   // Create a context and set an x property on it's global object.
   20514          10 :   LocalContext context0(nullptr, global_template);
   20515          25 :   CHECK(context0->Global()
   20516             :             ->Set(context0.local(), v8_str("x"), v8_num(42))
   20517             :             .FromJust());
   20518           5 :   v8::Local<v8::Object> global0 = context0->Global();
   20519             : 
   20520             :   // Create a context with a different security token so that the
   20521             :   // failed access check callback will be called on each access.
   20522          10 :   LocalContext context1(nullptr, global_template);
   20523          25 :   CHECK(context1->Global()
   20524             :             ->Set(context1.local(), v8_str("other"), global0)
   20525             :             .FromJust());
   20526             : 
   20527          10 :   v8::TryCatch try_catch(isolate);
   20528             : 
   20529             :   // Get property with failed access check.
   20530           5 :   CHECK(CompileRun("other.x").IsEmpty());
   20531           5 :   CHECK(try_catch.HasCaught());
   20532           5 :   try_catch.Reset();
   20533             : 
   20534             :   // Get element with failed access check.
   20535           5 :   CHECK(CompileRun("other[0]").IsEmpty());
   20536           5 :   CHECK(try_catch.HasCaught());
   20537           5 :   try_catch.Reset();
   20538             : 
   20539             :   // Set property with failed access check.
   20540           5 :   CHECK(CompileRun("other.x = new Object()").IsEmpty());
   20541           5 :   CHECK(try_catch.HasCaught());
   20542           5 :   try_catch.Reset();
   20543             : 
   20544             :   // Set element with failed access check.
   20545           5 :   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
   20546           5 :   CHECK(try_catch.HasCaught());
   20547           5 :   try_catch.Reset();
   20548             : 
   20549             :   // Get property attribute with failed access check.
   20550           5 :   CHECK(CompileRun("\'x\' in other").IsEmpty());
   20551           5 :   CHECK(try_catch.HasCaught());
   20552           5 :   try_catch.Reset();
   20553             : 
   20554             :   // Get property attribute for element with failed access check.
   20555           5 :   CHECK(CompileRun("0 in other").IsEmpty());
   20556           5 :   CHECK(try_catch.HasCaught());
   20557           5 :   try_catch.Reset();
   20558             : 
   20559             :   // Delete property.
   20560           5 :   CHECK(CompileRun("delete other.x").IsEmpty());
   20561           5 :   CHECK(try_catch.HasCaught());
   20562           5 :   try_catch.Reset();
   20563             : 
   20564             :   // Delete element.
   20565          10 :   CHECK(global0->Delete(context1.local(), 0).IsNothing());
   20566           5 :   CHECK(try_catch.HasCaught());
   20567           5 :   try_catch.Reset();
   20568             : 
   20569             :   // DefineAccessor.
   20570          20 :   CHECK(global0
   20571             :             ->SetAccessor(context1.local(), v8_str("x"), GetXValue, nullptr,
   20572             :                           v8_str("x"))
   20573             :             .IsNothing());
   20574           5 :   CHECK(try_catch.HasCaught());
   20575           5 :   try_catch.Reset();
   20576             : 
   20577             :   // Define JavaScript accessor.
   20578           5 :   CHECK(CompileRun(
   20579             :             "Object.prototype.__defineGetter__.call("
   20580             :             "    other, \'x\', function() { return 42; })").IsEmpty());
   20581           5 :   CHECK(try_catch.HasCaught());
   20582           5 :   try_catch.Reset();
   20583             : 
   20584             :   // LookupAccessor.
   20585           5 :   CHECK(CompileRun(
   20586             :             "Object.prototype.__lookupGetter__.call("
   20587             :             "    other, \'x\')").IsEmpty());
   20588           5 :   CHECK(try_catch.HasCaught());
   20589           5 :   try_catch.Reset();
   20590             : 
   20591             :   // HasOwnElement.
   20592           5 :   CHECK(CompileRun(
   20593             :             "Object.prototype.hasOwnProperty.call("
   20594             :             "other, \'0\')").IsEmpty());
   20595           5 :   CHECK(try_catch.HasCaught());
   20596           5 :   try_catch.Reset();
   20597             : 
   20598          10 :   CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
   20599           5 :   CHECK(try_catch.HasCaught());
   20600           5 :   try_catch.Reset();
   20601             : 
   20602          15 :   CHECK(
   20603             :       global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
   20604           5 :   CHECK(try_catch.HasCaught());
   20605           5 :   try_catch.Reset();
   20606             : 
   20607          15 :   CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
   20608             :             .IsNothing());
   20609           5 :   CHECK(try_catch.HasCaught());
   20610           5 :   try_catch.Reset();
   20611             : 
   20612             :   // Reset the failed access check callback so it does not influence
   20613             :   // the other tests.
   20614          10 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   20615           5 : }
   20616             : 
   20617             : 
   20618       28342 : TEST(IsolateNewDispose) {
   20619           5 :   v8::Isolate* current_isolate = CcTest::isolate();
   20620             :   v8::Isolate::CreateParams create_params;
   20621           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20622           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20623           5 :   CHECK_NOT_NULL(isolate);
   20624           5 :   CHECK(current_isolate != isolate);
   20625           5 :   CHECK(current_isolate == CcTest::isolate());
   20626             : 
   20627           5 :   isolate->SetFatalErrorHandler(StoringErrorCallback);
   20628           5 :   last_location = last_message = nullptr;
   20629           5 :   isolate->Dispose();
   20630           5 :   CHECK(!last_location);
   20631           5 :   CHECK(!last_message);
   20632           5 : }
   20633             : 
   20634             : 
   20635       28342 : UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   20636             :   v8::Isolate::CreateParams create_params;
   20637           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20638           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20639             :   {
   20640             :     v8::Isolate::Scope i_scope(isolate);
   20641          10 :     v8::HandleScope scope(isolate);
   20642           5 :     LocalContext context(isolate);
   20643             :     // Run something in this isolate.
   20644             :     ExpectTrue("true");
   20645           5 :     isolate->SetFatalErrorHandler(StoringErrorCallback);
   20646           5 :     last_location = last_message = nullptr;
   20647             :     // Still entered, should fail.
   20648           5 :     isolate->Dispose();
   20649           5 :     CHECK(last_location);
   20650           5 :     CHECK(last_message);
   20651             :   }
   20652           5 :   isolate->Dispose();
   20653           5 : }
   20654             : 
   20655             : 
   20656          40 : static void BreakArrayGuarantees(const char* script) {
   20657             :   v8::Isolate::CreateParams create_params;
   20658          40 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20659          40 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20660          40 :   isolate1->Enter();
   20661             :   v8::Persistent<v8::Context> context1;
   20662             :   {
   20663          40 :     v8::HandleScope scope(isolate1);
   20664          80 :     context1.Reset(isolate1, Context::New(isolate1));
   20665             :   }
   20666             : 
   20667             :   {
   20668          40 :     v8::HandleScope scope(isolate1);
   20669             :     v8::Local<v8::Context> context =
   20670             :         v8::Local<v8::Context>::New(isolate1, context1);
   20671             :     v8::Context::Scope context_scope(context);
   20672             :     v8::internal::Isolate* i_isolate =
   20673             :         reinterpret_cast<v8::internal::Isolate*>(isolate1);
   20674          40 :     CHECK(i_isolate->IsNoElementsProtectorIntact());
   20675             :     // Run something in new isolate.
   20676             :     CompileRun(script);
   20677          80 :     CHECK(!i_isolate->IsNoElementsProtectorIntact());
   20678             :   }
   20679          40 :   isolate1->Exit();
   20680          40 :   isolate1->Dispose();
   20681          40 : }
   20682             : 
   20683             : 
   20684       28342 : TEST(VerifyArrayPrototypeGuarantees) {
   20685             :   // Break fast array hole handling by element changes.
   20686           5 :   BreakArrayGuarantees("[].__proto__[1] = 3;");
   20687           5 :   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   20688           5 :   BreakArrayGuarantees("Array.prototype.push(1);");
   20689           5 :   BreakArrayGuarantees("Array.prototype.unshift(1);");
   20690             :   // Break fast array hole handling by changing length.
   20691           5 :   BreakArrayGuarantees("Array.prototype.length = 30;");
   20692             :   // Break fast array hole handling by prototype structure changes.
   20693           5 :   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   20694             :   // By sending elements to dictionary mode.
   20695             :   BreakArrayGuarantees(
   20696             :       "Object.defineProperty(Array.prototype, 0, {"
   20697           5 :       "  get: function() { return 3; }});");
   20698             :   BreakArrayGuarantees(
   20699             :       "Object.defineProperty(Object.prototype, 0, {"
   20700           5 :       "  get: function() { return 3; }});");
   20701           5 : }
   20702             : 
   20703             : 
   20704       28342 : TEST(RunTwoIsolatesOnSingleThread) {
   20705             :   // Run isolate 1.
   20706             :   v8::Isolate::CreateParams create_params;
   20707           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20708           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20709           5 :   isolate1->Enter();
   20710             :   v8::Persistent<v8::Context> context1;
   20711             :   {
   20712           5 :     v8::HandleScope scope(isolate1);
   20713          10 :     context1.Reset(isolate1, Context::New(isolate1));
   20714             :   }
   20715             : 
   20716             :   {
   20717           5 :     v8::HandleScope scope(isolate1);
   20718             :     v8::Local<v8::Context> context =
   20719             :         v8::Local<v8::Context>::New(isolate1, context1);
   20720             :     v8::Context::Scope context_scope(context);
   20721             :     // Run something in new isolate.
   20722             :     CompileRun("var foo = 'isolate 1';");
   20723          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20724             :   }
   20725             : 
   20726             :   // Run isolate 2.
   20727           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   20728             :   v8::Persistent<v8::Context> context2;
   20729             : 
   20730             :   {
   20731             :     v8::Isolate::Scope iscope(isolate2);
   20732          10 :     v8::HandleScope scope(isolate2);
   20733          10 :     context2.Reset(isolate2, Context::New(isolate2));
   20734             :     v8::Local<v8::Context> context =
   20735             :         v8::Local<v8::Context>::New(isolate2, context2);
   20736             :     v8::Context::Scope context_scope(context);
   20737             : 
   20738             :     // Run something in new isolate.
   20739             :     CompileRun("var foo = 'isolate 2';");
   20740           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20741             :   }
   20742             : 
   20743             :   {
   20744           5 :     v8::HandleScope scope(isolate1);
   20745             :     v8::Local<v8::Context> context =
   20746             :         v8::Local<v8::Context>::New(isolate1, context1);
   20747             :     v8::Context::Scope context_scope(context);
   20748             :     // Now again in isolate 1
   20749          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20750             :   }
   20751             : 
   20752           5 :   isolate1->Exit();
   20753             : 
   20754             :   // Run some stuff in default isolate.
   20755             :   v8::Persistent<v8::Context> context_default;
   20756             :   {
   20757           5 :     v8::Isolate* isolate = CcTest::isolate();
   20758             :     v8::Isolate::Scope iscope(isolate);
   20759          10 :     v8::HandleScope scope(isolate);
   20760          10 :     context_default.Reset(isolate, Context::New(isolate));
   20761             :   }
   20762             : 
   20763             :   {
   20764           5 :     v8::HandleScope scope(CcTest::isolate());
   20765             :     v8::Local<v8::Context> context =
   20766           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20767             :     v8::Context::Scope context_scope(context);
   20768             :     // Variables in other isolates should be not available, verify there
   20769             :     // is an exception.
   20770             :     ExpectTrue("function f() {"
   20771             :                "  try {"
   20772             :                "    foo;"
   20773             :                "    return false;"
   20774             :                "  } catch(e) {"
   20775             :                "    return true;"
   20776             :                "  }"
   20777             :                "};"
   20778             :                "var isDefaultIsolate = true;"
   20779           5 :                "f()");
   20780             :   }
   20781             : 
   20782           5 :   isolate1->Enter();
   20783             : 
   20784             :   {
   20785             :     v8::Isolate::Scope iscope(isolate2);
   20786          10 :     v8::HandleScope scope(isolate2);
   20787             :     v8::Local<v8::Context> context =
   20788             :         v8::Local<v8::Context>::New(isolate2, context2);
   20789             :     v8::Context::Scope context_scope(context);
   20790           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20791             :   }
   20792             : 
   20793             :   {
   20794           5 :     v8::HandleScope scope(v8::Isolate::GetCurrent());
   20795             :     v8::Local<v8::Context> context =
   20796           5 :         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   20797             :     v8::Context::Scope context_scope(context);
   20798          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20799             :   }
   20800             : 
   20801             :   {
   20802             :     v8::Isolate::Scope iscope(isolate2);
   20803             :     context2.Reset();
   20804             :   }
   20805             : 
   20806             :   context1.Reset();
   20807           5 :   isolate1->Exit();
   20808             : 
   20809           5 :   isolate2->SetFatalErrorHandler(StoringErrorCallback);
   20810           5 :   last_location = last_message = nullptr;
   20811             : 
   20812           5 :   isolate1->Dispose();
   20813           5 :   CHECK(!last_location);
   20814           5 :   CHECK(!last_message);
   20815             : 
   20816           5 :   isolate2->Dispose();
   20817           5 :   CHECK(!last_location);
   20818           5 :   CHECK(!last_message);
   20819             : 
   20820             :   // Check that default isolate still runs.
   20821             :   {
   20822           5 :     v8::HandleScope scope(CcTest::isolate());
   20823             :     v8::Local<v8::Context> context =
   20824           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20825             :     v8::Context::Scope context_scope(context);
   20826           5 :     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   20827             :   }
   20828           5 : }
   20829             : 
   20830             : 
   20831          20 : static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   20832             :   v8::Isolate::Scope isolate_scope(isolate);
   20833          40 :   v8::HandleScope scope(isolate);
   20834          20 :   LocalContext context(isolate);
   20835             :   i::ScopedVector<char> code(1024);
   20836             :   i::SNPrintF(code, "function fib(n) {"
   20837             :                     "  if (n <= 2) return 1;"
   20838             :                     "  return fib(n-1) + fib(n-2);"
   20839             :                     "}"
   20840          20 :                     "fib(%d)", limit);
   20841             :   Local<Value> value = CompileRun(code.start());
   20842          20 :   CHECK(value->IsNumber());
   20843          60 :   return static_cast<int>(value->NumberValue(context.local()).FromJust());
   20844             : }
   20845             : 
   20846           5 : class IsolateThread : public v8::base::Thread {
   20847             :  public:
   20848             :   explicit IsolateThread(int fib_limit)
   20849          10 :       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   20850             : 
   20851          10 :   void Run() override {
   20852             :     v8::Isolate::CreateParams create_params;
   20853          10 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20854          10 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20855          10 :     result_ = CalcFibonacci(isolate, fib_limit_);
   20856          10 :     isolate->Dispose();
   20857          10 :   }
   20858             : 
   20859             :   int result() { return result_; }
   20860             : 
   20861             :  private:
   20862             :   int fib_limit_;
   20863             :   int result_;
   20864             : };
   20865             : 
   20866             : 
   20867       28342 : TEST(MultipleIsolatesOnIndividualThreads) {
   20868             :   IsolateThread thread1(21);
   20869             :   IsolateThread thread2(12);
   20870             : 
   20871             :   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   20872           5 :   thread1.Start();
   20873           5 :   thread2.Start();
   20874             : 
   20875           5 :   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   20876           5 :   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   20877             : 
   20878           5 :   thread1.Join();
   20879           5 :   thread2.Join();
   20880             : 
   20881             :   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   20882             :   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   20883           5 :   CHECK_EQ(result1, 10946);
   20884           5 :   CHECK_EQ(result2, 144);
   20885           5 :   CHECK_EQ(result1, thread1.result());
   20886           5 :   CHECK_EQ(result2, thread2.result());
   20887           5 : }
   20888             : 
   20889             : 
   20890       28342 : TEST(IsolateDifferentContexts) {
   20891             :   v8::Isolate::CreateParams create_params;
   20892           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20893           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20894             :   Local<v8::Context> context;
   20895             :   {
   20896             :     v8::Isolate::Scope isolate_scope(isolate);
   20897          10 :     v8::HandleScope handle_scope(isolate);
   20898           5 :     context = v8::Context::New(isolate);
   20899             :     v8::Context::Scope context_scope(context);
   20900             :     Local<Value> v = CompileRun("2");
   20901           5 :     CHECK(v->IsNumber());
   20902          10 :     CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
   20903             :   }
   20904             :   {
   20905             :     v8::Isolate::Scope isolate_scope(isolate);
   20906          10 :     v8::HandleScope handle_scope(isolate);
   20907           5 :     context = v8::Context::New(isolate);
   20908             :     v8::Context::Scope context_scope(context);
   20909             :     Local<Value> v = CompileRun("22");
   20910           5 :     CHECK(v->IsNumber());
   20911          10 :     CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
   20912             :   }
   20913           5 :   isolate->Dispose();
   20914           5 : }
   20915             : 
   20916          20 : class InitDefaultIsolateThread : public v8::base::Thread {
   20917             :  public:
   20918             :   enum TestCase {
   20919             :     SetFatalHandler,
   20920             :     SetCounterFunction,
   20921             :     SetCreateHistogramFunction,
   20922             :     SetAddHistogramSampleFunction
   20923             :   };
   20924             : 
   20925             :   explicit InitDefaultIsolateThread(TestCase testCase)
   20926             :       : Thread(Options("InitDefaultIsolateThread")),
   20927             :         testCase_(testCase),
   20928          20 :         result_(false) {}
   20929             : 
   20930          20 :   void Run() override {
   20931             :     v8::Isolate::CreateParams create_params;
   20932          20 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20933          20 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20934          20 :     isolate->Enter();
   20935          20 :     switch (testCase_) {
   20936             :       case SetFatalHandler:
   20937           5 :         isolate->SetFatalErrorHandler(nullptr);
   20938           5 :         break;
   20939             : 
   20940             :       case SetCounterFunction:
   20941           5 :         CcTest::isolate()->SetCounterFunction(nullptr);
   20942           5 :         break;
   20943             : 
   20944             :       case SetCreateHistogramFunction:
   20945           5 :         CcTest::isolate()->SetCreateHistogramFunction(nullptr);
   20946           5 :         break;
   20947             : 
   20948             :       case SetAddHistogramSampleFunction:
   20949           5 :         CcTest::isolate()->SetAddHistogramSampleFunction(nullptr);
   20950           5 :         break;
   20951             :     }
   20952          20 :     isolate->Exit();
   20953          20 :     isolate->Dispose();
   20954          20 :     result_ = true;
   20955          20 :   }
   20956             : 
   20957             :   bool result() { return result_; }
   20958             : 
   20959             :  private:
   20960             :   TestCase testCase_;
   20961             :   bool result_;
   20962             : };
   20963             : 
   20964             : 
   20965          20 : static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   20966             :   InitDefaultIsolateThread thread(testCase);
   20967          20 :   thread.Start();
   20968          20 :   thread.Join();
   20969          20 :   CHECK(thread.result());
   20970          20 : }
   20971             : 
   20972       28342 : TEST(InitializeDefaultIsolateOnSecondaryThread_FatalHandler) {
   20973           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   20974           5 : }
   20975             : 
   20976       28342 : TEST(InitializeDefaultIsolateOnSecondaryThread_CounterFunction) {
   20977           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   20978           5 : }
   20979             : 
   20980       28342 : TEST(InitializeDefaultIsolateOnSecondaryThread_CreateHistogramFunction) {
   20981           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   20982           5 : }
   20983             : 
   20984       28342 : TEST(InitializeDefaultIsolateOnSecondaryThread_AddHistogramSampleFunction) {
   20985           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   20986           5 : }
   20987             : 
   20988             : 
   20989       28342 : TEST(StringCheckMultipleContexts) {
   20990             :   const char* code =
   20991             :       "(function() { return \"a\".charAt(0); })()";
   20992             : 
   20993             :   {
   20994             :     // Run the code twice in the first context to initialize the call IC.
   20995           5 :     LocalContext context1;
   20996          10 :     v8::HandleScope scope(context1->GetIsolate());
   20997           5 :     ExpectString(code, "a");
   20998          10 :     ExpectString(code, "a");
   20999             :   }
   21000             : 
   21001             :   {
   21002             :     // Change the String.prototype in the second context and check
   21003             :     // that the right function gets called.
   21004           5 :     LocalContext context2;
   21005          10 :     v8::HandleScope scope(context2->GetIsolate());
   21006             :     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   21007          10 :     ExpectString(code, "not a");
   21008             :   }
   21009           5 : }
   21010             : 
   21011             : 
   21012       28342 : TEST(NumberCheckMultipleContexts) {
   21013             :   const char* code =
   21014             :       "(function() { return (42).toString(); })()";
   21015             : 
   21016             :   {
   21017             :     // Run the code twice in the first context to initialize the call IC.
   21018           5 :     LocalContext context1;
   21019          10 :     v8::HandleScope scope(context1->GetIsolate());
   21020           5 :     ExpectString(code, "42");
   21021          10 :     ExpectString(code, "42");
   21022             :   }
   21023             : 
   21024             :   {
   21025             :     // Change the Number.prototype in the second context and check
   21026             :     // that the right function gets called.
   21027           5 :     LocalContext context2;
   21028          10 :     v8::HandleScope scope(context2->GetIsolate());
   21029             :     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   21030          10 :     ExpectString(code, "not 42");
   21031             :   }
   21032           5 : }
   21033             : 
   21034             : 
   21035       28342 : TEST(BooleanCheckMultipleContexts) {
   21036             :   const char* code =
   21037             :       "(function() { return true.toString(); })()";
   21038             : 
   21039             :   {
   21040             :     // Run the code twice in the first context to initialize the call IC.
   21041           5 :     LocalContext context1;
   21042          10 :     v8::HandleScope scope(context1->GetIsolate());
   21043           5 :     ExpectString(code, "true");
   21044          10 :     ExpectString(code, "true");
   21045             :   }
   21046             : 
   21047             :   {
   21048             :     // Change the Boolean.prototype in the second context and check
   21049             :     // that the right function gets called.
   21050           5 :     LocalContext context2;
   21051          10 :     v8::HandleScope scope(context2->GetIsolate());
   21052             :     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   21053          10 :     ExpectString(code, "");
   21054             :   }
   21055           5 : }
   21056             : 
   21057             : 
   21058       28342 : TEST(DontDeleteCellLoadIC) {
   21059             :   const char* function_code =
   21060             :       "function readCell() { while (true) { return cell; } }";
   21061             : 
   21062             :   {
   21063             :     // Run the code twice in the first context to initialize the load
   21064             :     // IC for a don't delete cell.
   21065           5 :     LocalContext context1;
   21066          10 :     v8::HandleScope scope(context1->GetIsolate());
   21067             :     CompileRun("var cell = \"first\";");
   21068           5 :     ExpectBoolean("delete cell", false);
   21069             :     CompileRun(function_code);
   21070           5 :     ExpectString("readCell()", "first");
   21071          10 :     ExpectString("readCell()", "first");
   21072             :   }
   21073             : 
   21074             :   {
   21075             :     // Use a deletable cell in the second context.
   21076           5 :     LocalContext context2;
   21077          10 :     v8::HandleScope scope(context2->GetIsolate());
   21078             :     CompileRun("cell = \"second\";");
   21079             :     CompileRun(function_code);
   21080           5 :     ExpectString("readCell()", "second");
   21081           5 :     ExpectBoolean("delete cell", true);
   21082             :     ExpectString("(function() {"
   21083             :                  "  try {"
   21084             :                  "    return readCell();"
   21085             :                  "  } catch(e) {"
   21086             :                  "    return e.toString();"
   21087             :                  "  }"
   21088             :                  "})()",
   21089           5 :                  "ReferenceError: cell is not defined");
   21090             :     CompileRun("cell = \"new_second\";");
   21091           5 :     CcTest::CollectAllGarbage();
   21092           5 :     ExpectString("readCell()", "new_second");
   21093          10 :     ExpectString("readCell()", "new_second");
   21094             :   }
   21095           5 : }
   21096             : 
   21097             : 
   21098          10 : class Visitor42 : public v8::PersistentHandleVisitor {
   21099             :  public:
   21100             :   explicit Visitor42(v8::Persistent<v8::Object>* object)
   21101          10 :       : counter_(0), object_(object) { }
   21102             : 
   21103          10 :   void VisitPersistentHandle(Persistent<Value>* value,
   21104             :                              uint16_t class_id) override {
   21105          10 :     if (class_id != 42) return;
   21106          10 :     CHECK_EQ(42, value->WrapperClassId());
   21107          10 :     v8::Isolate* isolate = CcTest::isolate();
   21108          10 :     v8::HandleScope handle_scope(isolate);
   21109             :     v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   21110          10 :     v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
   21111          10 :     CHECK(handle->IsObject());
   21112          20 :     CHECK(Local<Object>::Cast(handle)
   21113             :               ->Equals(isolate->GetCurrentContext(), object)
   21114             :               .FromJust());
   21115          10 :     ++counter_;
   21116             :   }
   21117             : 
   21118             :   int counter_;
   21119             :   v8::Persistent<v8::Object>* object_;
   21120             : };
   21121             : 
   21122             : 
   21123       28342 : TEST(PersistentHandleVisitor) {
   21124           5 :   LocalContext context;
   21125           5 :   v8::Isolate* isolate = context->GetIsolate();
   21126          10 :   v8::HandleScope scope(isolate);
   21127           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   21128           5 :   CHECK_EQ(0, object.WrapperClassId());
   21129             :   object.SetWrapperClassId(42);
   21130           5 :   CHECK_EQ(42, object.WrapperClassId());
   21131             : 
   21132             :   Visitor42 visitor(&object);
   21133           5 :   isolate->VisitHandlesWithClassIds(&visitor);
   21134           5 :   CHECK_EQ(1, visitor.counter_);
   21135             : 
   21136           5 :   object.Reset();
   21137           5 : }
   21138             : 
   21139             : 
   21140       28342 : TEST(WrapperClassId) {
   21141           5 :   LocalContext context;
   21142           5 :   v8::Isolate* isolate = context->GetIsolate();
   21143          10 :   v8::HandleScope scope(isolate);
   21144           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   21145           5 :   CHECK_EQ(0, object.WrapperClassId());
   21146             :   object.SetWrapperClassId(65535);
   21147           5 :   CHECK_EQ(65535, object.WrapperClassId());
   21148           5 :   object.Reset();
   21149           5 : }
   21150             : 
   21151             : 
   21152       28342 : TEST(PersistentHandleInNewSpaceVisitor) {
   21153           5 :   LocalContext context;
   21154           5 :   v8::Isolate* isolate = context->GetIsolate();
   21155          10 :   v8::HandleScope scope(isolate);
   21156           5 :   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
   21157           5 :   CHECK_EQ(0, object1.WrapperClassId());
   21158             :   object1.SetWrapperClassId(42);
   21159           5 :   CHECK_EQ(42, object1.WrapperClassId());
   21160             : 
   21161           5 :   CcTest::CollectAllGarbage();
   21162           5 :   CcTest::CollectAllGarbage();
   21163             : 
   21164           5 :   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
   21165           5 :   CHECK_EQ(0, object2.WrapperClassId());
   21166             :   object2.SetWrapperClassId(42);
   21167           5 :   CHECK_EQ(42, object2.WrapperClassId());
   21168             : 
   21169             :   Visitor42 visitor(&object2);
   21170           5 :   isolate->VisitHandlesForPartialDependence(&visitor);
   21171           5 :   CHECK_EQ(1, visitor.counter_);
   21172             : 
   21173             :   object1.Reset();
   21174           5 :   object2.Reset();
   21175           5 : }
   21176             : 
   21177             : 
   21178       28342 : TEST(RegExp) {
   21179           5 :   LocalContext context;
   21180          10 :   v8::HandleScope scope(context->GetIsolate());
   21181             : 
   21182             :   v8::Local<v8::RegExp> re =
   21183           5 :       v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
   21184           5 :           .ToLocalChecked();
   21185           5 :   CHECK(re->IsRegExp());
   21186          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
   21187           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   21188             : 
   21189             :   re = v8::RegExp::New(context.local(), v8_str("bar"),
   21190             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   21191           5 :                                                       v8::RegExp::kGlobal))
   21192           5 :            .ToLocalChecked();
   21193           5 :   CHECK(re->IsRegExp());
   21194          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
   21195           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   21196             :            static_cast<int>(re->GetFlags()));
   21197             : 
   21198             :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   21199             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   21200           5 :                                                       v8::RegExp::kMultiline))
   21201           5 :            .ToLocalChecked();
   21202           5 :   CHECK(re->IsRegExp());
   21203          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   21204           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   21205             :            static_cast<int>(re->GetFlags()));
   21206             : 
   21207             :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   21208             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
   21209           5 :                                                       v8::RegExp::kSticky))
   21210           5 :            .ToLocalChecked();
   21211           5 :   CHECK(re->IsRegExp());
   21212          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   21213           5 :   CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
   21214             :            static_cast<int>(re->GetFlags()));
   21215             : 
   21216             :   re = CompileRun("/quux/").As<v8::RegExp>();
   21217           5 :   CHECK(re->IsRegExp());
   21218          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   21219           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   21220             : 
   21221             :   re = CompileRun("/quux/gm").As<v8::RegExp>();
   21222           5 :   CHECK(re->IsRegExp());
   21223          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   21224           5 :   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   21225             :            static_cast<int>(re->GetFlags()));
   21226             : 
   21227             :   // Override the RegExp constructor and check the API constructor
   21228             :   // still works.
   21229             :   CompileRun("RegExp = function() {}");
   21230             : 
   21231           5 :   re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
   21232           5 :            .ToLocalChecked();
   21233           5 :   CHECK(re->IsRegExp());
   21234          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
   21235           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   21236             : 
   21237             :   re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
   21238             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   21239           5 :                                                       v8::RegExp::kMultiline))
   21240           5 :            .ToLocalChecked();
   21241           5 :   CHECK(re->IsRegExp());
   21242          20 :   CHECK(
   21243             :       re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
   21244           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   21245             :            static_cast<int>(re->GetFlags()));
   21246             : 
   21247          25 :   CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
   21248             :   ExpectTrue("re.test('FoobarbaZ')");
   21249             : 
   21250             :   // RegExps are objects on which you can set properties.
   21251             :   re->Set(context.local(), v8_str("property"),
   21252          20 :           v8::Integer::New(context->GetIsolate(), 32))
   21253          10 :       .FromJust();
   21254             :   v8::Local<v8::Value> value(CompileRun("re.property"));
   21255          10 :   CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
   21256             : 
   21257          10 :   v8::TryCatch try_catch(context->GetIsolate());
   21258          10 :   CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
   21259             :             .IsEmpty());
   21260           5 :   CHECK(try_catch.HasCaught());
   21261          25 :   CHECK(context->Global()
   21262             :             ->Set(context.local(), v8_str("ex"), try_catch.Exception())
   21263             :             .FromJust());
   21264           5 :   ExpectTrue("ex instanceof SyntaxError");
   21265           5 : }
   21266             : 
   21267             : 
   21268       28343 : THREADED_TEST(Equals) {
   21269           6 :   LocalContext localContext;
   21270          12 :   v8::HandleScope handleScope(localContext->GetIsolate());
   21271             : 
   21272           6 :   v8::Local<v8::Object> globalProxy = localContext->Global();
   21273           6 :   v8::Local<Value> global = globalProxy->GetPrototype();
   21274             : 
   21275           6 :   CHECK(global->StrictEquals(global));
   21276           6 :   CHECK(!global->StrictEquals(globalProxy));
   21277           6 :   CHECK(!globalProxy->StrictEquals(global));
   21278           6 :   CHECK(globalProxy->StrictEquals(globalProxy));
   21279             : 
   21280          12 :   CHECK(global->Equals(localContext.local(), global).FromJust());
   21281          12 :   CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
   21282          12 :   CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
   21283          18 :   CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
   21284           6 : }
   21285             : 
   21286             : 
   21287           5 : static void Getter(v8::Local<v8::Name> property,
   21288             :                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   21289           5 :   info.GetReturnValue().Set(v8_str("42!"));
   21290           5 : }
   21291             : 
   21292             : 
   21293           5 : static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   21294           5 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
   21295             :   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
   21296          15 :               v8_str("universalAnswer"))
   21297          10 :       .FromJust();
   21298             :   info.GetReturnValue().Set(result);
   21299           5 : }
   21300             : 
   21301             : 
   21302       28342 : TEST(NamedEnumeratorAndForIn) {
   21303           5 :   LocalContext context;
   21304           5 :   v8::Isolate* isolate = context->GetIsolate();
   21305          10 :   v8::HandleScope handle_scope(isolate);
   21306           5 :   v8::Context::Scope context_scope(context.local());
   21307             : 
   21308           5 :   v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   21309             :   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21310           5 :       Getter, nullptr, nullptr, nullptr, Enumerator));
   21311          30 :   CHECK(context->Global()
   21312             :             ->Set(context.local(), v8_str("o"),
   21313             :                   tmpl->NewInstance(context.local()).ToLocalChecked())
   21314             :             .FromJust());
   21315             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   21316             :       CompileRun("var result = []; for (var k in o) result.push(k); result"));
   21317           5 :   CHECK_EQ(1u, result->Length());
   21318          20 :   CHECK(v8_str("universalAnswer")
   21319             :             ->Equals(context.local(),
   21320             :                      result->Get(context.local(), 0).ToLocalChecked())
   21321           5 :             .FromJust());
   21322           5 : }
   21323             : 
   21324             : 
   21325       28342 : TEST(DefinePropertyPostDetach) {
   21326           5 :   LocalContext context;
   21327          10 :   v8::HandleScope scope(context->GetIsolate());
   21328           5 :   v8::Local<v8::Object> proxy = context->Global();
   21329             :   v8::Local<v8::Function> define_property =
   21330             :       CompileRun(
   21331             :           "(function() {"
   21332             :           "  Object.defineProperty("
   21333             :           "    this,"
   21334             :           "    1,"
   21335             :           "    { configurable: true, enumerable: true, value: 3 });"
   21336             :           "})")
   21337             :           .As<Function>();
   21338           5 :   context->DetachGlobal();
   21339          15 :   CHECK(define_property->Call(context.local(), proxy, 0, nullptr).IsEmpty());
   21340           5 : }
   21341             : 
   21342             : 
   21343          36 : static void InstallContextId(v8::Local<Context> context, int id) {
   21344             :   Context::Scope scope(context);
   21345         144 :   CHECK(CompileRun("Object.prototype")
   21346             :             .As<Object>()
   21347             :             ->Set(context, v8_str("context_id"),
   21348             :                   v8::Integer::New(context->GetIsolate(), id))
   21349             :             .FromJust());
   21350          36 : }
   21351             : 
   21352             : 
   21353         126 : static void CheckContextId(v8::Local<Object> object, int expected) {
   21354         126 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   21355         504 :   CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
   21356             :                          .ToLocalChecked()
   21357             :                          ->Int32Value(context)
   21358             :                          .FromJust());
   21359         126 : }
   21360             : 
   21361             : 
   21362       28343 : THREADED_TEST(CreationContext) {
   21363           6 :   v8::Isolate* isolate = CcTest::isolate();
   21364           6 :   HandleScope handle_scope(isolate);
   21365           6 :   Local<Context> context1 = Context::New(isolate);
   21366           6 :   InstallContextId(context1, 1);
   21367           6 :   Local<Context> context2 = Context::New(isolate);
   21368           6 :   InstallContextId(context2, 2);
   21369           6 :   Local<Context> context3 = Context::New(isolate);
   21370           6 :   InstallContextId(context3, 3);
   21371             : 
   21372           6 :   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   21373             : 
   21374             :   Local<Object> object1;
   21375             :   Local<Function> func1;
   21376             :   {
   21377             :     Context::Scope scope(context1);
   21378           6 :     object1 = Object::New(isolate);
   21379           6 :     func1 = tmpl->GetFunction(context1).ToLocalChecked();
   21380             :   }
   21381             : 
   21382             :   Local<Object> object2;
   21383             :   Local<Function> func2;
   21384             :   {
   21385             :     Context::Scope scope(context2);
   21386           6 :     object2 = Object::New(isolate);
   21387           6 :     func2 = tmpl->GetFunction(context2).ToLocalChecked();
   21388             :   }
   21389             : 
   21390             :   Local<Object> instance1;
   21391             :   Local<Object> instance2;
   21392             : 
   21393             :   {
   21394             :     Context::Scope scope(context3);
   21395             :     instance1 = func1->NewInstance(context3).ToLocalChecked();
   21396             :     instance2 = func2->NewInstance(context3).ToLocalChecked();
   21397             :   }
   21398             : 
   21399             :   {
   21400           6 :     Local<Context> other_context = Context::New(isolate);
   21401             :     Context::Scope scope(other_context);
   21402          12 :     CHECK(object1->CreationContext() == context1);
   21403           6 :     CheckContextId(object1, 1);
   21404          12 :     CHECK(func1->CreationContext() == context1);
   21405           6 :     CheckContextId(func1, 1);
   21406          12 :     CHECK(instance1->CreationContext() == context1);
   21407           6 :     CheckContextId(instance1, 1);
   21408          12 :     CHECK(object2->CreationContext() == context2);
   21409           6 :     CheckContextId(object2, 2);
   21410          12 :     CHECK(func2->CreationContext() == context2);
   21411           6 :     CheckContextId(func2, 2);
   21412          12 :     CHECK(instance2->CreationContext() == context2);
   21413           6 :     CheckContextId(instance2, 2);
   21414             :   }
   21415             : 
   21416             :   {
   21417             :     Context::Scope scope(context1);
   21418          12 :     CHECK(object1->CreationContext() == context1);
   21419           6 :     CheckContextId(object1, 1);
   21420          12 :     CHECK(func1->CreationContext() == context1);
   21421           6 :     CheckContextId(func1, 1);
   21422          12 :     CHECK(instance1->CreationContext() == context1);
   21423           6 :     CheckContextId(instance1, 1);
   21424          12 :     CHECK(object2->CreationContext() == context2);
   21425           6 :     CheckContextId(object2, 2);
   21426          12 :     CHECK(func2->CreationContext() == context2);
   21427           6 :     CheckContextId(func2, 2);
   21428          12 :     CHECK(instance2->CreationContext() == context2);
   21429           6 :     CheckContextId(instance2, 2);
   21430             :   }
   21431             : 
   21432             :   {
   21433             :     Context::Scope scope(context2);
   21434          12 :     CHECK(object1->CreationContext() == context1);
   21435           6 :     CheckContextId(object1, 1);
   21436          12 :     CHECK(func1->CreationContext() == context1);
   21437           6 :     CheckContextId(func1, 1);
   21438          12 :     CHECK(instance1->CreationContext() == context1);
   21439           6 :     CheckContextId(instance1, 1);
   21440          12 :     CHECK(object2->CreationContext() == context2);
   21441           6 :     CheckContextId(object2, 2);
   21442          12 :     CHECK(func2->CreationContext() == context2);
   21443           6 :     CheckContextId(func2, 2);
   21444          12 :     CHECK(instance2->CreationContext() == context2);
   21445           6 :     CheckContextId(instance2, 2);
   21446           6 :   }
   21447           6 : }
   21448             : 
   21449             : 
   21450       28343 : THREADED_TEST(CreationContextOfJsFunction) {
   21451           6 :   HandleScope handle_scope(CcTest::isolate());
   21452           6 :   Local<Context> context = Context::New(CcTest::isolate());
   21453           6 :   InstallContextId(context, 1);
   21454             : 
   21455             :   Local<Object> function;
   21456             :   {
   21457             :     Context::Scope scope(context);
   21458             :     function = CompileRun("function foo() {}; foo").As<Object>();
   21459             :   }
   21460             : 
   21461           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   21462             :   Context::Scope scope(other_context);
   21463          12 :   CHECK(function->CreationContext() == context);
   21464          12 :   CheckContextId(function, 1);
   21465           6 : }
   21466             : 
   21467             : 
   21468       28343 : THREADED_TEST(CreationContextOfJsBoundFunction) {
   21469           6 :   HandleScope handle_scope(CcTest::isolate());
   21470           6 :   Local<Context> context1 = Context::New(CcTest::isolate());
   21471           6 :   InstallContextId(context1, 1);
   21472           6 :   Local<Context> context2 = Context::New(CcTest::isolate());
   21473           6 :   InstallContextId(context2, 2);
   21474             : 
   21475             :   Local<Function> target_function;
   21476             :   {
   21477             :     Context::Scope scope(context1);
   21478             :     target_function = CompileRun("function foo() {}; foo").As<Function>();
   21479             :   }
   21480             : 
   21481             :   Local<Function> bound_function1, bound_function2;
   21482             :   {
   21483             :     Context::Scope scope(context2);
   21484          24 :     CHECK(context2->Global()
   21485             :               ->Set(context2, v8_str("foo"), target_function)
   21486             :               .FromJust());
   21487             :     bound_function1 = CompileRun("foo.bind(1)").As<Function>();
   21488             :     bound_function2 =
   21489             :         CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
   21490             :   }
   21491             : 
   21492           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   21493             :   Context::Scope scope(other_context);
   21494          12 :   CHECK(bound_function1->CreationContext() == context1);
   21495           6 :   CheckContextId(bound_function1, 1);
   21496          12 :   CHECK(bound_function2->CreationContext() == context1);
   21497          12 :   CheckContextId(bound_function2, 1);
   21498           6 : }
   21499             : 
   21500             : 
   21501          20 : void HasOwnPropertyIndexedPropertyGetter(
   21502             :     uint32_t index,
   21503             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21504          20 :   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   21505          20 : }
   21506             : 
   21507             : 
   21508          10 : void HasOwnPropertyNamedPropertyGetter(
   21509             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   21510          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21511          20 :           .FromJust()) {
   21512           5 :     info.GetReturnValue().Set(v8_str("yes"));
   21513             :   }
   21514          10 : }
   21515             : 
   21516             : 
   21517          50 : void HasOwnPropertyIndexedPropertyQuery(
   21518             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   21519          50 :   if (index == 42) info.GetReturnValue().Set(1);
   21520          50 : }
   21521             : 
   21522             : 
   21523          10 : void HasOwnPropertyNamedPropertyQuery(
   21524             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   21525          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   21526          20 :           .FromJust()) {
   21527             :     info.GetReturnValue().Set(1);
   21528             :   }
   21529          10 : }
   21530             : 
   21531             : 
   21532          10 : void HasOwnPropertyNamedPropertyQuery2(
   21533             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   21534          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
   21535          20 :           .FromJust()) {
   21536             :     info.GetReturnValue().Set(1);
   21537             :   }
   21538          10 : }
   21539             : 
   21540           0 : void HasOwnPropertyAccessorGetter(
   21541             :     Local<String> property,
   21542             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   21543           0 :   info.GetReturnValue().Set(v8_str("yes"));
   21544           0 : }
   21545             : 
   21546           5 : void HasOwnPropertyAccessorNameGetter(
   21547             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   21548           5 :   info.GetReturnValue().Set(v8_str("yes"));
   21549           5 : }
   21550             : 
   21551       28342 : TEST(HasOwnProperty) {
   21552           5 :   LocalContext env;
   21553           5 :   v8::Isolate* isolate = env->GetIsolate();
   21554          10 :   v8::HandleScope scope(isolate);
   21555             :   { // Check normal properties and defined getters.
   21556             :     Local<Value> value = CompileRun(
   21557             :         "function Foo() {"
   21558             :         "    this.foo = 11;"
   21559             :         "    this.__defineGetter__('baz', function() { return 1; });"
   21560             :         "};"
   21561             :         "function Bar() { "
   21562             :         "    this.bar = 13;"
   21563             :         "    this.__defineGetter__('bla', function() { return 2; });"
   21564             :         "};"
   21565             :         "Bar.prototype = new Foo();"
   21566             :         "new Bar();");
   21567           5 :     CHECK(value->IsObject());
   21568           5 :     Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
   21569          15 :     CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
   21570          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21571          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21572          15 :     CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
   21573          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
   21574          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
   21575             :   }
   21576             :   { // Check named getter interceptors.
   21577           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21578             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21579           5 :         HasOwnPropertyNamedPropertyGetter));
   21580           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21581          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   21582          10 :     CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
   21583          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21584          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21585             :   }
   21586             :   { // Check indexed getter interceptors.
   21587           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21588             :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21589           5 :         HasOwnPropertyIndexedPropertyGetter));
   21590           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21591          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   21592          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   21593          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
   21594          10 :     CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
   21595          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21596             :   }
   21597             :   { // Check named query interceptors.
   21598           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21599             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21600           5 :         nullptr, nullptr, HasOwnPropertyNamedPropertyQuery));
   21601           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21602          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21603          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21604             :   }
   21605             :   { // Check indexed query interceptors.
   21606           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21607             :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21608           5 :         nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   21609           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21610          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   21611          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   21612          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
   21613          10 :     CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
   21614             :   }
   21615             :   { // Check callbacks.
   21616           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21617           5 :     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   21618           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21619          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21620          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21621             :   }
   21622             :   { // Check that query wins on disagreement.
   21623           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21624             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21625             :         HasOwnPropertyNamedPropertyGetter, nullptr,
   21626           5 :         HasOwnPropertyNamedPropertyQuery2));
   21627           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21628          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21629          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21630             :   }
   21631             :   {  // Check that non-internalized keys are handled correctly.
   21632           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21633             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21634           5 :         HasOwnPropertyAccessorNameGetter));
   21635           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21636          25 :     env->Global()->Set(env.local(), v8_str("obj"), instance).FromJust();
   21637             :     const char* src =
   21638             :         "var dyn_string = 'this string ';"
   21639             :         "dyn_string += 'does not exist elsewhere';"
   21640             :         "({}).hasOwnProperty.call(obj, dyn_string)";
   21641           5 :     CHECK(CompileRun(src)->BooleanValue(isolate));
   21642           5 :   }
   21643           5 : }
   21644             : 
   21645             : 
   21646       28342 : TEST(IndexedInterceptorWithStringProto) {
   21647           5 :   v8::Isolate* isolate = CcTest::isolate();
   21648           5 :   v8::HandleScope scope(isolate);
   21649           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21650             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21651           5 :       nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   21652          10 :   LocalContext context;
   21653          30 :   CHECK(context->Global()
   21654             :             ->Set(context.local(), v8_str("obj"),
   21655             :                   templ->NewInstance(context.local()).ToLocalChecked())
   21656             :             .FromJust());
   21657             :   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   21658             :   // These should be intercepted.
   21659           5 :   CHECK(CompileRun("42 in obj")->BooleanValue(isolate));
   21660           5 :   CHECK(CompileRun("'42' in obj")->BooleanValue(isolate));
   21661             :   // These should fall through to the String prototype.
   21662           5 :   CHECK(CompileRun("0 in obj")->BooleanValue(isolate));
   21663           5 :   CHECK(CompileRun("'0' in obj")->BooleanValue(isolate));
   21664             :   // And these should both fail.
   21665           5 :   CHECK(!CompileRun("32 in obj")->BooleanValue(isolate));
   21666          10 :   CHECK(!CompileRun("'32' in obj")->BooleanValue(isolate));
   21667           5 : }
   21668             : 
   21669             : 
   21670          18 : void CheckCodeGenerationAllowed() {
   21671          18 :   Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   21672             :   Local<Value> result = CompileRun("eval('42')");
   21673          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21674             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   21675          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21676             :   result = CompileRun("var f = new Function('return 42'); f()");
   21677          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21678          18 : }
   21679             : 
   21680             : 
   21681          12 : void CheckCodeGenerationDisallowed() {
   21682          12 :   TryCatch try_catch(CcTest::isolate());
   21683             : 
   21684             :   Local<Value> result = CompileRun("eval('42')");
   21685          12 :   CHECK(result.IsEmpty());
   21686          12 :   CHECK(try_catch.HasCaught());
   21687          12 :   try_catch.Reset();
   21688             : 
   21689             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   21690          12 :   CHECK(result.IsEmpty());
   21691          12 :   CHECK(try_catch.HasCaught());
   21692          12 :   try_catch.Reset();
   21693             : 
   21694             :   result = CompileRun("var f = new Function('return 42'); f()");
   21695          12 :   CHECK(result.IsEmpty());
   21696          12 :   CHECK(try_catch.HasCaught());
   21697          12 : }
   21698             : 
   21699             : char first_fourty_bytes[41];
   21700             : 
   21701          23 : bool CodeGenerationAllowed(Local<Context> context, Local<String> source) {
   21702          23 :   String::Utf8Value str(CcTest::isolate(), source);
   21703             :   size_t len = std::min(sizeof(first_fourty_bytes) - 1,
   21704          46 :                         static_cast<size_t>(str.length()));
   21705          23 :   strncpy(first_fourty_bytes, *str, len);
   21706          23 :   first_fourty_bytes[len] = 0;
   21707          23 :   ApiTestFuzzer::Fuzz();
   21708          23 :   return true;
   21709             : }
   21710             : 
   21711          23 : bool CodeGenerationDisallowed(Local<Context> context, Local<String> source) {
   21712          23 :   ApiTestFuzzer::Fuzz();
   21713          23 :   return false;
   21714             : }
   21715             : 
   21716             : 
   21717       28343 : THREADED_TEST(AllowCodeGenFromStrings) {
   21718           6 :   LocalContext context;
   21719          12 :   v8::HandleScope scope(context->GetIsolate());
   21720             : 
   21721             :   // eval and the Function constructor allowed by default.
   21722           6 :   CHECK(context->IsCodeGenerationFromStringsAllowed());
   21723           6 :   CheckCodeGenerationAllowed();
   21724             : 
   21725             :   // Disallow eval and the Function constructor.
   21726           6 :   context->AllowCodeGenerationFromStrings(false);
   21727           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21728           6 :   CheckCodeGenerationDisallowed();
   21729             : 
   21730             :   // Allow again.
   21731           6 :   context->AllowCodeGenerationFromStrings(true);
   21732           6 :   CheckCodeGenerationAllowed();
   21733             : 
   21734             :   // Disallow but setting a global callback that will allow the calls.
   21735           6 :   context->AllowCodeGenerationFromStrings(false);
   21736             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21737           6 :       &CodeGenerationAllowed);
   21738           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21739           6 :   CheckCodeGenerationAllowed();
   21740             : 
   21741             :   // Set a callback that disallows the code generation.
   21742             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21743           6 :       &CodeGenerationDisallowed);
   21744           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21745          12 :   CheckCodeGenerationDisallowed();
   21746           6 : }
   21747             : 
   21748             : 
   21749       28342 : TEST(SetErrorMessageForCodeGenFromStrings) {
   21750           5 :   LocalContext context;
   21751          10 :   v8::HandleScope scope(context->GetIsolate());
   21752          10 :   TryCatch try_catch(context->GetIsolate());
   21753             : 
   21754           5 :   Local<String> message = v8_str("Message");
   21755           5 :   Local<String> expected_message = v8_str("Uncaught EvalError: Message");
   21756             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21757           5 :       &CodeGenerationDisallowed);
   21758           5 :   context->AllowCodeGenerationFromStrings(false);
   21759           5 :   context->SetErrorMessageForCodeGenerationFromStrings(message);
   21760             :   Local<Value> result = CompileRun("eval('42')");
   21761           5 :   CHECK(result.IsEmpty());
   21762           5 :   CHECK(try_catch.HasCaught());
   21763          10 :   Local<String> actual_message = try_catch.Message()->Get();
   21764          20 :   CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
   21765           5 : }
   21766             : 
   21767       28342 : TEST(CaptureSourceForCodeGenFromStrings) {
   21768           5 :   LocalContext context;
   21769          10 :   v8::HandleScope scope(context->GetIsolate());
   21770          10 :   TryCatch try_catch(context->GetIsolate());
   21771             : 
   21772             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21773           5 :       &CodeGenerationAllowed);
   21774           5 :   context->AllowCodeGenerationFromStrings(false);
   21775             :   CompileRun("eval('42')");
   21776          10 :   CHECK(!strcmp(first_fourty_bytes, "42"));
   21777           5 : }
   21778             : 
   21779           6 : static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21780           6 : }
   21781             : 
   21782             : 
   21783       28343 : THREADED_TEST(CallAPIFunctionOnNonObject) {
   21784           6 :   LocalContext context;
   21785           6 :   v8::Isolate* isolate = context->GetIsolate();
   21786          12 :   v8::HandleScope scope(isolate);
   21787             :   Local<FunctionTemplate> templ =
   21788           6 :       v8::FunctionTemplate::New(isolate, NonObjectThis);
   21789             :   Local<Function> function =
   21790          12 :       templ->GetFunction(context.local()).ToLocalChecked();
   21791          30 :   CHECK(context->Global()
   21792             :             ->Set(context.local(), v8_str("f"), function)
   21793             :             .FromJust());
   21794          12 :   TryCatch try_catch(isolate);
   21795           6 :   CompileRun("f.call(2)");
   21796           6 : }
   21797             : 
   21798             : 
   21799             : // Regression test for issue 1470.
   21800       28343 : THREADED_TEST(ReadOnlyIndexedProperties) {
   21801           6 :   v8::Isolate* isolate = CcTest::isolate();
   21802           6 :   v8::HandleScope scope(isolate);
   21803           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21804             : 
   21805          12 :   LocalContext context;
   21806          12 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   21807          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   21808             :   obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
   21809          24 :                          v8::ReadOnly)
   21810          12 :       .FromJust();
   21811          24 :   obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
   21812          30 :   CHECK(v8_str("DONT_CHANGE")
   21813             :             ->Equals(context.local(),
   21814             :                      obj->Get(context.local(), v8_str("1")).ToLocalChecked())
   21815             :             .FromJust());
   21816             :   obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
   21817          24 :                          v8::ReadOnly)
   21818          12 :       .FromJust();
   21819          18 :   obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
   21820          24 :   CHECK(v8_str("DONT_CHANGE")
   21821             :             ->Equals(context.local(),
   21822             :                      obj->Get(context.local(), v8_num(2)).ToLocalChecked())
   21823             :             .FromJust());
   21824             : 
   21825             :   // Test non-smi case.
   21826             :   obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
   21827          24 :                          v8_str("DONT_CHANGE"), v8::ReadOnly)
   21828          12 :       .FromJust();
   21829          24 :   obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
   21830          30 :   CHECK(v8_str("DONT_CHANGE")
   21831             :             ->Equals(context.local(),
   21832             :                      obj->Get(context.local(), v8_str("2000000000"))
   21833             :                          .ToLocalChecked())
   21834           6 :             .FromJust());
   21835           6 : }
   21836             : 
   21837          12 : static int CountLiveMapsInMapCache(i::Context context) {
   21838          24 :   i::WeakFixedArray map_cache = i::WeakFixedArray::cast(context->map_cache());
   21839             :   int length = map_cache->length();
   21840             :   int count = 0;
   21841        1548 :   for (int i = 0; i < length; i++) {
   21842        3072 :     if (map_cache->Get(i)->IsWeak()) count++;
   21843             :   }
   21844          12 :   return count;
   21845             : }
   21846             : 
   21847             : 
   21848       28343 : THREADED_TEST(Regress1516) {
   21849           6 :   LocalContext context;
   21850          12 :   v8::HandleScope scope(context->GetIsolate());
   21851             : 
   21852             :   // Object with 20 properties is not a common case, so it should be removed
   21853             :   // from the cache after GC.
   21854           6 :   { v8::HandleScope temp_scope(context->GetIsolate());
   21855             :     CompileRun(
   21856             :         "({"
   21857             :         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
   21858             :         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
   21859             :         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
   21860             :         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
   21861           6 :         "})");
   21862             :   }
   21863             : 
   21864           6 :   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
   21865           6 :   CHECK_LE(1, elements);
   21866             : 
   21867             :   // We have to abort incremental marking here to abandon black pages.
   21868           6 :   CcTest::PreciseCollectAllGarbage();
   21869             : 
   21870          12 :   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
   21871           6 : }
   21872             : 
   21873             : 
   21874       28343 : THREADED_TEST(Regress93759) {
   21875           6 :   v8::Isolate* isolate = CcTest::isolate();
   21876           6 :   HandleScope scope(isolate);
   21877             : 
   21878             :   // Template for object with security check.
   21879           6 :   Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
   21880           6 :   no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   21881             : 
   21882             :   // Templates for objects with hidden prototypes and possibly security check.
   21883             :   Local<FunctionTemplate> hidden_proto_template =
   21884           6 :       v8::FunctionTemplate::New(isolate);
   21885           6 :   hidden_proto_template->SetHiddenPrototype(true);
   21886             : 
   21887             :   Local<FunctionTemplate> protected_hidden_proto_template =
   21888           6 :       v8::FunctionTemplate::New(isolate);
   21889             :   protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
   21890          12 :       AccessAlwaysBlocked);
   21891           6 :   protected_hidden_proto_template->SetHiddenPrototype(true);
   21892             : 
   21893             :   // Context for "foreign" objects used in test.
   21894           6 :   Local<Context> context = v8::Context::New(isolate);
   21895           6 :   context->Enter();
   21896             : 
   21897             :   // Plain object, no security check.
   21898           6 :   Local<Object> simple_object = Object::New(isolate);
   21899             : 
   21900             :   // Object with explicit security check.
   21901             :   Local<Object> protected_object =
   21902           6 :       no_proto_template->NewInstance(context).ToLocalChecked();
   21903             : 
   21904             :   // JSGlobalProxy object, always have security check.
   21905           6 :   Local<Object> proxy_object = context->Global();
   21906             : 
   21907             :   // Global object, the  prototype of proxy_object. No security checks.
   21908             :   Local<Object> global_object =
   21909          18 :       proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
   21910             : 
   21911             :   // Hidden prototype without security check.
   21912             :   Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
   21913           6 :                                        .ToLocalChecked()
   21914             :                                        ->NewInstance(context)
   21915             :                                        .ToLocalChecked();
   21916             :   Local<Object> object_with_hidden =
   21917           6 :     Object::New(isolate);
   21918          12 :   object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
   21919             : 
   21920           6 :   context->Exit();
   21921             : 
   21922          12 :   LocalContext context2;
   21923           6 :   v8::Local<v8::Object> global = context2->Global();
   21924             : 
   21925             :   // Setup global variables.
   21926          18 :   CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
   21927             :             .FromJust());
   21928          18 :   CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
   21929             :             .FromJust());
   21930          18 :   CHECK(global->Set(context2.local(), v8_str("global"), global_object)
   21931             :             .FromJust());
   21932          18 :   CHECK(
   21933             :       global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
   21934          18 :   CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
   21935             :             .FromJust());
   21936             : 
   21937             :   Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
   21938          12 :   CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
   21939             :             .FromJust());
   21940             : 
   21941             :   Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
   21942           6 :   CHECK(result2->IsNull());
   21943             : 
   21944             :   Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
   21945          12 :   CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
   21946             :             .FromJust());
   21947             : 
   21948             :   Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
   21949           6 :   CHECK(result4->IsNull());
   21950             : 
   21951             :   Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
   21952          24 :   CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
   21953             :                                               ->ToObject(context2.local())
   21954             :                                               .ToLocalChecked()
   21955             :                                               ->GetPrototype())
   21956           6 :             .FromJust());
   21957           6 : }
   21958             : 
   21959             : 
   21960          84 : static void TestReceiver(Local<Value> expected_result,
   21961             :                          Local<Value> expected_receiver,
   21962             :                          const char* code) {
   21963             :   Local<Value> result = CompileRun(code);
   21964          84 :   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   21965          84 :   CHECK(result->IsObject());
   21966         252 :   CHECK(expected_receiver
   21967             :             ->Equals(context,
   21968             :                      result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
   21969             :             .FromJust());
   21970         252 :   CHECK(expected_result
   21971             :             ->Equals(context,
   21972             :                      result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
   21973             :             .FromJust());
   21974          84 : }
   21975             : 
   21976             : 
   21977       28343 : THREADED_TEST(ForeignFunctionReceiver) {
   21978           6 :   v8::Isolate* isolate = CcTest::isolate();
   21979           6 :   HandleScope scope(isolate);
   21980             : 
   21981             :   // Create two contexts with different "id" properties ('i' and 'o').
   21982             :   // Call a function both from its own context and from a the foreign
   21983             :   // context, and see what "this" is bound to (returning both "this"
   21984             :   // and "this.id" for comparison).
   21985             : 
   21986           6 :   Local<Context> foreign_context = v8::Context::New(isolate);
   21987           6 :   foreign_context->Enter();
   21988             :   Local<Value> foreign_function =
   21989             :     CompileRun("function func() { return { 0: this.id, "
   21990             :                "                           1: this, "
   21991             :                "                           toString: function() { "
   21992             :                "                               return this[0];"
   21993             :                "                           }"
   21994             :                "                         };"
   21995             :                "}"
   21996             :                "var id = 'i';"
   21997             :                "func;");
   21998           6 :   CHECK(foreign_function->IsFunction());
   21999           6 :   foreign_context->Exit();
   22000             : 
   22001          12 :   LocalContext context;
   22002             : 
   22003           6 :   Local<String> password = v8_str("Password");
   22004             :   // Don't get hit by security checks when accessing foreign_context's
   22005             :   // global receiver (aka. global proxy).
   22006           6 :   context->SetSecurityToken(password);
   22007           6 :   foreign_context->SetSecurityToken(password);
   22008             : 
   22009           6 :   Local<String> i = v8_str("i");
   22010           6 :   Local<String> o = v8_str("o");
   22011           6 :   Local<String> id = v8_str("id");
   22012             : 
   22013             :   CompileRun("function ownfunc() { return { 0: this.id, "
   22014             :              "                              1: this, "
   22015             :              "                              toString: function() { "
   22016             :              "                                  return this[0];"
   22017             :              "                              }"
   22018             :              "                             };"
   22019             :              "}"
   22020             :              "var id = 'o';"
   22021             :              "ownfunc");
   22022          30 :   CHECK(context->Global()
   22023             :             ->Set(context.local(), v8_str("func"), foreign_function)
   22024             :             .FromJust());
   22025             : 
   22026             :   // Sanity check the contexts.
   22027          24 :   CHECK(
   22028             :       i->Equals(
   22029             :            context.local(),
   22030             :            foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
   22031             :           .FromJust());
   22032          30 :   CHECK(o->Equals(context.local(),
   22033             :                   context->Global()->Get(context.local(), id).ToLocalChecked())
   22034             :             .FromJust());
   22035             : 
   22036             :   // Checking local function's receiver.
   22037             :   // Calling function using its call/apply methods.
   22038          12 :   TestReceiver(o, context->Global(), "ownfunc.call()");
   22039          12 :   TestReceiver(o, context->Global(), "ownfunc.apply()");
   22040             :   // Making calls through built-in functions.
   22041          12 :   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   22042          12 :   CHECK(
   22043             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
   22044             :           .FromJust());
   22045          12 :   CHECK(
   22046             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
   22047             :           .FromJust());
   22048          12 :   CHECK(
   22049             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
   22050             :           .FromJust());
   22051             :   // Calling with environment record as base.
   22052          12 :   TestReceiver(o, context->Global(), "ownfunc()");
   22053             :   // Calling with no base.
   22054          12 :   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   22055             : 
   22056             :   // Checking foreign function return value.
   22057             :   // Calling function using its call/apply methods.
   22058          12 :   TestReceiver(i, foreign_context->Global(), "func.call()");
   22059          12 :   TestReceiver(i, foreign_context->Global(), "func.apply()");
   22060             :   // Calling function using another context's call/apply methods.
   22061             :   TestReceiver(i, foreign_context->Global(),
   22062          12 :                "Function.prototype.call.call(func)");
   22063             :   TestReceiver(i, foreign_context->Global(),
   22064          12 :                "Function.prototype.call.apply(func)");
   22065             :   TestReceiver(i, foreign_context->Global(),
   22066          12 :                "Function.prototype.apply.call(func)");
   22067             :   TestReceiver(i, foreign_context->Global(),
   22068          12 :                "Function.prototype.apply.apply(func)");
   22069             :   // Making calls through built-in functions.
   22070          12 :   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   22071             :   // ToString(func()) is func()[0], i.e., the returned this.id.
   22072          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
   22073             :             .FromJust());
   22074          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
   22075             :             .FromJust());
   22076          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
   22077             :             .FromJust());
   22078             : 
   22079             :   // Calling with environment record as base.
   22080          12 :   TestReceiver(i, foreign_context->Global(), "func()");
   22081             :   // Calling with no base.
   22082          18 :   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   22083           6 : }
   22084             : 
   22085             : 
   22086             : uint8_t callback_fired = 0;
   22087             : uint8_t before_call_entered_callback_count1 = 0;
   22088             : uint8_t before_call_entered_callback_count2 = 0;
   22089             : 
   22090             : 
   22091           5 : void CallCompletedCallback1(v8::Isolate*) {
   22092           5 :   v8::base::OS::Print("Firing callback 1.\n");
   22093           5 :   callback_fired ^= 1;  // Toggle first bit.
   22094           5 : }
   22095             : 
   22096             : 
   22097          15 : void CallCompletedCallback2(v8::Isolate*) {
   22098          15 :   v8::base::OS::Print("Firing callback 2.\n");
   22099          15 :   callback_fired ^= 2;  // Toggle second bit.
   22100          15 : }
   22101             : 
   22102             : 
   22103          20 : void BeforeCallEnteredCallback1(v8::Isolate*) {
   22104          20 :   v8::base::OS::Print("Firing before call entered callback 1.\n");
   22105          20 :   before_call_entered_callback_count1++;
   22106          20 : }
   22107             : 
   22108             : 
   22109          60 : void BeforeCallEnteredCallback2(v8::Isolate*) {
   22110          60 :   v8::base::OS::Print("Firing before call entered callback 2.\n");
   22111          60 :   before_call_entered_callback_count2++;
   22112          60 : }
   22113             : 
   22114             : 
   22115          60 : void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22116             :   int32_t level =
   22117         180 :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   22118          60 :   if (level < 3) {
   22119          45 :     level++;
   22120          45 :     v8::base::OS::Print("Entering recursion level %d.\n", level);
   22121             :     char script[64];
   22122             :     i::Vector<char> script_vector(script, sizeof(script));
   22123          45 :     i::SNPrintF(script_vector, "recursion(%d)", level);
   22124             :     CompileRun(script_vector.start());
   22125          45 :     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   22126          90 :     CHECK_EQ(0, callback_fired);
   22127             :   } else {
   22128          15 :     v8::base::OS::Print("Recursion ends.\n");
   22129          30 :     CHECK_EQ(0, callback_fired);
   22130             :   }
   22131          60 : }
   22132             : 
   22133             : 
   22134       28342 : TEST(CallCompletedCallback) {
   22135           5 :   LocalContext env;
   22136          10 :   v8::HandleScope scope(env->GetIsolate());
   22137             :   v8::Local<v8::FunctionTemplate> recursive_runtime =
   22138           5 :       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   22139             :   env->Global()
   22140             :       ->Set(env.local(), v8_str("recursion"),
   22141          30 :             recursive_runtime->GetFunction(env.local()).ToLocalChecked())
   22142          10 :       .FromJust();
   22143             :   // Adding the same callback a second time has no effect.
   22144           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   22145           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   22146           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   22147           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   22148           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
   22149           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   22150           5 :   v8::base::OS::Print("--- Script (1) ---\n");
   22151           5 :   callback_fired = 0;
   22152           5 :   before_call_entered_callback_count1 = 0;
   22153           5 :   before_call_entered_callback_count2 = 0;
   22154             :   Local<Script> script =
   22155           5 :       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   22156           5 :   script->Run(env.local()).ToLocalChecked();
   22157          10 :   CHECK_EQ(3, callback_fired);
   22158          10 :   CHECK_EQ(4, before_call_entered_callback_count1);
   22159          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   22160             : 
   22161           5 :   v8::base::OS::Print("\n--- Script (2) ---\n");
   22162           5 :   callback_fired = 0;
   22163           5 :   before_call_entered_callback_count1 = 0;
   22164           5 :   before_call_entered_callback_count2 = 0;
   22165           5 :   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   22166             :   env->GetIsolate()->RemoveBeforeCallEnteredCallback(
   22167           5 :       BeforeCallEnteredCallback1);
   22168           5 :   script->Run(env.local()).ToLocalChecked();
   22169          10 :   CHECK_EQ(2, callback_fired);
   22170          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   22171          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   22172             : 
   22173           5 :   v8::base::OS::Print("\n--- Function ---\n");
   22174           5 :   callback_fired = 0;
   22175           5 :   before_call_entered_callback_count1 = 0;
   22176           5 :   before_call_entered_callback_count2 = 0;
   22177             :   Local<Function> recursive_function = Local<Function>::Cast(
   22178          25 :       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   22179           5 :   v8::Local<Value> args[] = {v8_num(0)};
   22180          15 :   recursive_function->Call(env.local(), env->Global(), 1, args)
   22181           5 :       .ToLocalChecked();
   22182          10 :   CHECK_EQ(2, callback_fired);
   22183          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   22184          15 :   CHECK_EQ(4, before_call_entered_callback_count2);
   22185           5 : }
   22186             : 
   22187             : 
   22188           5 : void CallCompletedCallbackNoException(v8::Isolate*) {
   22189           5 :   v8::HandleScope scope(CcTest::isolate());
   22190           5 :   CompileRun("1+1;");
   22191           5 : }
   22192             : 
   22193             : 
   22194           5 : void CallCompletedCallbackException(v8::Isolate*) {
   22195           5 :   v8::HandleScope scope(CcTest::isolate());
   22196           5 :   CompileRun("throw 'second exception';");
   22197           5 : }
   22198             : 
   22199             : 
   22200       28342 : TEST(CallCompletedCallbackOneException) {
   22201           5 :   LocalContext env;
   22202          10 :   v8::HandleScope scope(env->GetIsolate());
   22203           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   22204           5 :   CompileRun("throw 'exception';");
   22205           5 : }
   22206             : 
   22207             : 
   22208       28342 : TEST(CallCompletedCallbackTwoExceptions) {
   22209           5 :   LocalContext env;
   22210          10 :   v8::HandleScope scope(env->GetIsolate());
   22211           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   22212           5 :   CompileRun("throw 'first exception';");
   22213           5 : }
   22214             : 
   22215             : 
   22216         135 : static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   22217          45 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   22218          45 :   v8::HandleScope scope(info.GetIsolate());
   22219             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   22220          90 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   22221          45 :   CompileRun("ext1Calls++;");
   22222          45 : }
   22223             : 
   22224             : 
   22225         150 : static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   22226          50 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   22227          50 :   v8::HandleScope scope(info.GetIsolate());
   22228             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   22229         100 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   22230          50 :   CompileRun("ext2Calls++;");
   22231          50 : }
   22232             : 
   22233             : void* g_passed_to_three = nullptr;
   22234             : 
   22235          10 : static void MicrotaskThree(void* data) {
   22236          10 :   g_passed_to_three = data;
   22237          10 : }
   22238             : 
   22239             : 
   22240       28342 : TEST(EnqueueMicrotask) {
   22241           5 :   LocalContext env;
   22242          10 :   v8::HandleScope scope(env->GetIsolate());
   22243           5 :   CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
   22244             :   CompileRun(
   22245             :       "var ext1Calls = 0;"
   22246             :       "var ext2Calls = 0;");
   22247             :   CompileRun("1+1;");
   22248          15 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22249          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22250             : 
   22251             :   env->GetIsolate()->EnqueueMicrotask(
   22252          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22253             :   CompileRun("1+1;");
   22254          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22255          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22256             : 
   22257             :   env->GetIsolate()->EnqueueMicrotask(
   22258          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22259             :   env->GetIsolate()->EnqueueMicrotask(
   22260          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22261             :   CompileRun("1+1;");
   22262          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22263          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22264             : 
   22265             :   env->GetIsolate()->EnqueueMicrotask(
   22266          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22267             :   CompileRun("1+1;");
   22268          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22269          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22270             : 
   22271             :   CompileRun("1+1;");
   22272          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22273          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22274             : 
   22275           5 :   g_passed_to_three = nullptr;
   22276           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   22277             :   CompileRun("1+1;");
   22278           5 :   CHECK(!g_passed_to_three);
   22279          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22280          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22281             : 
   22282             :   int dummy;
   22283             :   env->GetIsolate()->EnqueueMicrotask(
   22284          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22285           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   22286             :   env->GetIsolate()->EnqueueMicrotask(
   22287          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22288             :   CompileRun("1+1;");
   22289           5 :   CHECK_EQ(&dummy, g_passed_to_three);
   22290          15 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22291          15 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22292          10 :   g_passed_to_three = nullptr;
   22293           5 : }
   22294             : 
   22295             : 
   22296           5 : static void MicrotaskExceptionOne(
   22297          10 :     const v8::FunctionCallbackInfo<Value>& info) {
   22298           5 :   v8::HandleScope scope(info.GetIsolate());
   22299             :   CompileRun("exception1Calls++;");
   22300             :   info.GetIsolate()->ThrowException(
   22301          10 :       v8::Exception::Error(v8_str("first")));
   22302           5 : }
   22303             : 
   22304             : 
   22305           5 : static void MicrotaskExceptionTwo(
   22306          10 :     const v8::FunctionCallbackInfo<Value>& info) {
   22307           5 :   v8::HandleScope scope(info.GetIsolate());
   22308             :   CompileRun("exception2Calls++;");
   22309             :   info.GetIsolate()->ThrowException(
   22310          10 :       v8::Exception::Error(v8_str("second")));
   22311           5 : }
   22312             : 
   22313             : 
   22314       28342 : TEST(RunMicrotasksIgnoresThrownExceptions) {
   22315           5 :   LocalContext env;
   22316           5 :   v8::Isolate* isolate = env->GetIsolate();
   22317          10 :   v8::HandleScope scope(isolate);
   22318             :   CompileRun(
   22319             :       "var exception1Calls = 0;"
   22320             :       "var exception2Calls = 0;");
   22321             :   isolate->EnqueueMicrotask(
   22322          10 :       Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
   22323             :   isolate->EnqueueMicrotask(
   22324          10 :       Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
   22325          10 :   TryCatch try_catch(isolate);
   22326             :   CompileRun("1+1;");
   22327           5 :   CHECK(!try_catch.HasCaught());
   22328          15 :   CHECK_EQ(1,
   22329             :            CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
   22330          15 :   CHECK_EQ(1,
   22331           5 :            CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
   22332           5 : }
   22333             : 
   22334           5 : static void ThrowExceptionMicrotask(void* data) {
   22335          10 :   CcTest::isolate()->ThrowException(v8_str("exception"));
   22336           5 : }
   22337             : 
   22338             : int microtask_callback_count = 0;
   22339             : 
   22340           5 : static void IncrementCounterMicrotask(void* data) {
   22341           5 :   microtask_callback_count++;
   22342           5 : }
   22343             : 
   22344       28342 : TEST(RunMicrotasksIgnoresThrownExceptionsFromApi) {
   22345           5 :   LocalContext env;
   22346           5 :   v8::Isolate* isolate = CcTest::isolate();
   22347           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   22348          10 :   v8::HandleScope scope(isolate);
   22349          10 :   v8::TryCatch try_catch(isolate);
   22350             :   {
   22351           5 :     CHECK(!isolate->IsExecutionTerminating());
   22352           5 :     isolate->EnqueueMicrotask(ThrowExceptionMicrotask);
   22353           5 :     isolate->EnqueueMicrotask(IncrementCounterMicrotask);
   22354           5 :     isolate->RunMicrotasks();
   22355           5 :     CHECK_EQ(1, microtask_callback_count);
   22356           5 :     CHECK(!try_catch.HasCaught());
   22357           5 :   }
   22358           5 : }
   22359             : 
   22360             : uint8_t microtasks_completed_callback_count = 0;
   22361             : 
   22362             : 
   22363          25 : static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
   22364          25 :   ++microtasks_completed_callback_count;
   22365          25 : }
   22366             : 
   22367             : 
   22368       28342 : TEST(SetAutorunMicrotasks) {
   22369           5 :   LocalContext env;
   22370          10 :   v8::HandleScope scope(env->GetIsolate());
   22371             :   env->GetIsolate()->AddMicrotasksCompletedCallback(
   22372           5 :       &MicrotasksCompletedCallback);
   22373             :   CompileRun(
   22374             :       "var ext1Calls = 0;"
   22375             :       "var ext2Calls = 0;");
   22376             :   CompileRun("1+1;");
   22377          15 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22378          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22379           5 :   CHECK_EQ(0u, microtasks_completed_callback_count);
   22380             : 
   22381             :   env->GetIsolate()->EnqueueMicrotask(
   22382          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22383             :   CompileRun("1+1;");
   22384          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22385          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22386           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   22387             : 
   22388           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   22389             :   env->GetIsolate()->EnqueueMicrotask(
   22390          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22391             :   env->GetIsolate()->EnqueueMicrotask(
   22392          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22393             :   CompileRun("1+1;");
   22394          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22395          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22396           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   22397             : 
   22398           5 :   env->GetIsolate()->RunMicrotasks();
   22399          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22400          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22401           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   22402             : 
   22403             :   env->GetIsolate()->EnqueueMicrotask(
   22404          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22405             :   CompileRun("1+1;");
   22406          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22407          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22408           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   22409             : 
   22410           5 :   env->GetIsolate()->RunMicrotasks();
   22411          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22412          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22413           5 :   CHECK_EQ(3u, microtasks_completed_callback_count);
   22414             : 
   22415           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   22416             :   env->GetIsolate()->EnqueueMicrotask(
   22417          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22418             :   CompileRun("1+1;");
   22419          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22420          15 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22421           5 :   CHECK_EQ(4u, microtasks_completed_callback_count);
   22422             : 
   22423             :   env->GetIsolate()->EnqueueMicrotask(
   22424          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22425             :   {
   22426           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   22427             :     CompileRun("1+1;");
   22428          15 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22429          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22430           5 :     CHECK_EQ(4u, microtasks_completed_callback_count);
   22431             :   }
   22432             : 
   22433             :   CompileRun("1+1;");
   22434          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22435          15 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22436           5 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   22437             : 
   22438             :   env->GetIsolate()->RemoveMicrotasksCompletedCallback(
   22439           5 :       &MicrotasksCompletedCallback);
   22440             :   env->GetIsolate()->EnqueueMicrotask(
   22441          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22442             :   CompileRun("1+1;");
   22443          15 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22444          15 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22445          10 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   22446           5 : }
   22447             : 
   22448             : 
   22449       28342 : TEST(RunMicrotasksWithoutEnteringContext) {
   22450           5 :   v8::Isolate* isolate = CcTest::isolate();
   22451           5 :   HandleScope handle_scope(isolate);
   22452           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   22453           5 :   Local<Context> context = Context::New(isolate);
   22454             :   {
   22455             :     Context::Scope context_scope(context);
   22456             :     CompileRun("var ext1Calls = 0;");
   22457             :     isolate->EnqueueMicrotask(
   22458          10 :         Function::New(context, MicrotaskOne).ToLocalChecked());
   22459             :   }
   22460           5 :   isolate->RunMicrotasks();
   22461             :   {
   22462             :     Context::Scope context_scope(context);
   22463          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
   22464             :   }
   22465           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   22466           5 : }
   22467             : 
   22468           6 : static void Regress808911_MicrotaskCallback(void* data) {
   22469             :   // So here we expect "current context" to be context1 and
   22470             :   // "entered or microtask context" to be context2.
   22471             :   v8::Isolate* isolate = static_cast<v8::Isolate*>(data);
   22472          12 :   CHECK(isolate->GetCurrentContext() !=
   22473             :         isolate->GetEnteredOrMicrotaskContext());
   22474           6 : }
   22475             : 
   22476           6 : static void Regress808911_CurrentContextWrapper(
   22477           6 :     const v8::FunctionCallbackInfo<Value>& info) {
   22478             :   // So here we expect "current context" to be context1 and
   22479             :   // "entered or microtask context" to be context2.
   22480             :   v8::Isolate* isolate = info.GetIsolate();
   22481          12 :   CHECK(isolate->GetCurrentContext() !=
   22482             :         isolate->GetEnteredOrMicrotaskContext());
   22483           6 :   isolate->EnqueueMicrotask(Regress808911_MicrotaskCallback, isolate);
   22484           6 :   isolate->RunMicrotasks();
   22485           6 : }
   22486             : 
   22487       28343 : THREADED_TEST(Regress808911) {
   22488           6 :   v8::Isolate* isolate = CcTest::isolate();
   22489           6 :   HandleScope handle_scope(isolate);
   22490           6 :   Local<Context> context1 = Context::New(isolate);
   22491             :   Local<Function> function;
   22492             :   {
   22493             :     Context::Scope context_scope(context1);
   22494           6 :     function = Function::New(context1, Regress808911_CurrentContextWrapper)
   22495           6 :                    .ToLocalChecked();
   22496             :   }
   22497           6 :   Local<Context> context2 = Context::New(isolate);
   22498             :   Context::Scope context_scope(context2);
   22499           6 :   function->CallAsFunction(context2, v8::Undefined(isolate), 0, nullptr)
   22500          12 :       .ToLocalChecked();
   22501           6 : }
   22502             : 
   22503       28342 : TEST(ScopedMicrotasks) {
   22504           5 :   LocalContext env;
   22505          10 :   v8::HandleScope handles(env->GetIsolate());
   22506           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
   22507             :   {
   22508             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   22509           5 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   22510             :     env->GetIsolate()->EnqueueMicrotask(
   22511          10 :         Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22512             :     CompileRun(
   22513             :         "var ext1Calls = 0;"
   22514             :         "var ext2Calls = 0;");
   22515             :     CompileRun("1+1;");
   22516          15 :     CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22517          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22518             :     {
   22519             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   22520           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   22521             :       CompileRun("1+1;");
   22522          15 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22523          15 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22524             :       {
   22525             :         v8::MicrotasksScope scope3(env->GetIsolate(),
   22526           5 :                                    v8::MicrotasksScope::kRunMicrotasks);
   22527             :         CompileRun("1+1;");
   22528          15 :         CHECK_EQ(0,
   22529             :                  CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22530          15 :         CHECK_EQ(0,
   22531           5 :                  CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22532             :       }
   22533          15 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22534          15 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22535             :     }
   22536          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22537          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22538             :     env->GetIsolate()->EnqueueMicrotask(
   22539          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22540             :   }
   22541             : 
   22542             :   {
   22543             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22544           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22545          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22546          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22547             :   }
   22548             : 
   22549             :   {
   22550             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   22551           5 :                                v8::MicrotasksScope::kRunMicrotasks);
   22552             :     CompileRun("1+1;");
   22553          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22554          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22555             :     {
   22556             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   22557           5 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   22558             :     }
   22559          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22560          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22561             :   }
   22562             : 
   22563             :   {
   22564             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22565           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22566          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22567          15 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22568             :     env->GetIsolate()->EnqueueMicrotask(
   22569          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22570             :   }
   22571             : 
   22572             :   {
   22573           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   22574             :     {
   22575             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   22576           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   22577             :     }
   22578             :     v8::MicrotasksScope scope3(env->GetIsolate(),
   22579          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   22580          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22581          20 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22582             :   }
   22583             : 
   22584             :   {
   22585             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   22586           5 :                                v8::MicrotasksScope::kRunMicrotasks);
   22587           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22588          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22589          15 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22590             :   }
   22591             : 
   22592             :   {
   22593             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22594           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22595          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22596          15 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22597             :   }
   22598             : 
   22599           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22600             : 
   22601             :   {
   22602             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22603           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22604          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22605          15 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22606             :     env->GetIsolate()->EnqueueMicrotask(
   22607          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   22608             :   }
   22609             : 
   22610           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22611             : 
   22612             :   {
   22613             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22614           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22615          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22616          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22617             :   }
   22618             : 
   22619             :   env->GetIsolate()->EnqueueMicrotask(
   22620          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   22621             :   {
   22622           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   22623           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22624             :     v8::MicrotasksScope scope2(env->GetIsolate(),
   22625          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   22626          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22627          20 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22628             :   }
   22629             : 
   22630           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   22631             : 
   22632             :   {
   22633             :     v8::MicrotasksScope scope(env->GetIsolate(),
   22634           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   22635          15 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   22636          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   22637             :   }
   22638             : 
   22639          10 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   22640           5 : }
   22641             : 
   22642             : namespace {
   22643             : 
   22644          35 : void AssertCowElements(bool expected, const char* source) {
   22645             :   Local<Value> object = CompileRun(source);
   22646             :   i::Handle<i::JSObject> array =
   22647          35 :       i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*object.As<Object>()));
   22648          35 :   CHECK_EQ(expected, array->elements()->IsCowArray());
   22649          35 : }
   22650             : 
   22651             : }  // namespace
   22652             : 
   22653       28342 : TEST(CheckCOWArraysCreatedRuntimeCounter) {
   22654           5 :   LocalContext env;
   22655          10 :   v8::HandleScope scope(env->GetIsolate());
   22656           5 :   AssertCowElements(true, "[1, 2, 3]");
   22657           5 :   AssertCowElements(false, "[[1], 2, 3]");
   22658           5 :   AssertCowElements(true, "[[1], 2, 3][0]");
   22659           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.foo)");
   22660           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.bar)");
   22661           5 :   AssertCowElements(false, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo)");
   22662          10 :   AssertCowElements(true, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo[3])");
   22663           5 : }
   22664             : 
   22665             : 
   22666       28342 : TEST(StaticGetters) {
   22667           5 :   LocalContext context;
   22668             :   i::Factory* factory = CcTest::i_isolate()->factory();
   22669           5 :   v8::Isolate* isolate = CcTest::isolate();
   22670          10 :   v8::HandleScope scope(isolate);
   22671             :   i::Handle<i::Object> undefined_value = factory->undefined_value();
   22672           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   22673             :   i::Handle<i::Object> null_value = factory->null_value();
   22674           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   22675             :   i::Handle<i::Object> true_value = factory->true_value();
   22676           5 :   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   22677             :   i::Handle<i::Object> false_value = factory->false_value();
   22678          10 :   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   22679           5 : }
   22680             : 
   22681             : 
   22682       28342 : UNINITIALIZED_TEST(IsolateEmbedderData) {
   22683           5 :   CcTest::DisableAutomaticDispose();
   22684             :   v8::Isolate::CreateParams create_params;
   22685           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   22686           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   22687           5 :   isolate->Enter();
   22688             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   22689          25 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22690          20 :     CHECK(!isolate->GetData(slot));
   22691          20 :     CHECK(!i_isolate->GetData(slot));
   22692             :   }
   22693          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22694          20 :     void* data = reinterpret_cast<void*>(0xACCE55ED + slot);
   22695             :     isolate->SetData(slot, data);
   22696             :   }
   22697          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22698          20 :     void* data = reinterpret_cast<void*>(0xACCE55ED + slot);
   22699          20 :     CHECK_EQ(data, isolate->GetData(slot));
   22700          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   22701             :   }
   22702          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22703          20 :     void* data = reinterpret_cast<void*>(0xDECEA5ED + slot);
   22704             :     isolate->SetData(slot, data);
   22705             :   }
   22706          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22707          20 :     void* data = reinterpret_cast<void*>(0xDECEA5ED + slot);
   22708          20 :     CHECK_EQ(data, isolate->GetData(slot));
   22709          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   22710             :   }
   22711           5 :   isolate->Exit();
   22712           5 :   isolate->Dispose();
   22713           5 : }
   22714             : 
   22715             : 
   22716       28342 : TEST(StringEmpty) {
   22717           5 :   LocalContext context;
   22718             :   i::Factory* factory = CcTest::i_isolate()->factory();
   22719           5 :   v8::Isolate* isolate = CcTest::isolate();
   22720          10 :   v8::HandleScope scope(isolate);
   22721             :   i::Handle<i::Object> empty_string = factory->empty_string();
   22722          10 :   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   22723           5 : }
   22724             : 
   22725             : 
   22726             : static int instance_checked_getter_count = 0;
   22727         120 : static void InstanceCheckedGetter(
   22728             :     Local<String> name,
   22729             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   22730         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   22731             :             .FromJust());
   22732         120 :   instance_checked_getter_count++;
   22733         120 :   info.GetReturnValue().Set(v8_num(11));
   22734         120 : }
   22735             : 
   22736             : 
   22737             : static int instance_checked_setter_count = 0;
   22738         120 : static void InstanceCheckedSetter(Local<String> name,
   22739             :                       Local<Value> value,
   22740             :                       const v8::PropertyCallbackInfo<void>& info) {
   22741         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   22742             :             .FromJust());
   22743         480 :   CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
   22744             :             .FromJust());
   22745         120 :   instance_checked_setter_count++;
   22746         120 : }
   22747             : 
   22748             : 
   22749         420 : static void CheckInstanceCheckedResult(int getters, int setters,
   22750             :                                        bool expects_callbacks,
   22751             :                                        TryCatch* try_catch) {
   22752         420 :   if (expects_callbacks) {
   22753         240 :     CHECK(!try_catch->HasCaught());
   22754         240 :     CHECK_EQ(getters, instance_checked_getter_count);
   22755         240 :     CHECK_EQ(setters, instance_checked_setter_count);
   22756             :   } else {
   22757         180 :     CHECK(try_catch->HasCaught());
   22758         180 :     CHECK_EQ(0, instance_checked_getter_count);
   22759         180 :     CHECK_EQ(0, instance_checked_setter_count);
   22760             :   }
   22761         420 :   try_catch->Reset();
   22762         420 : }
   22763             : 
   22764             : 
   22765          42 : static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   22766          42 :   instance_checked_getter_count = 0;
   22767          42 :   instance_checked_setter_count = 0;
   22768          42 :   TryCatch try_catch(CcTest::isolate());
   22769             : 
   22770             :   // Test path through generic runtime code.
   22771             :   CompileRun("obj.foo");
   22772          42 :   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   22773             :   CompileRun("obj.foo = 23");
   22774          42 :   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   22775             : 
   22776             :   // Test path through generated LoadIC and StoredIC.
   22777             :   CompileRun("function test_get(o) { o.foo; }"
   22778             :              "test_get(obj);");
   22779          42 :   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   22780             :   CompileRun("test_get(obj);");
   22781          42 :   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   22782             :   CompileRun("test_get(obj);");
   22783          42 :   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   22784             :   CompileRun("function test_set(o) { o.foo = 23; }"
   22785             :              "test_set(obj);");
   22786          42 :   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   22787             :   CompileRun("test_set(obj);");
   22788          42 :   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   22789             :   CompileRun("test_set(obj);");
   22790          42 :   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   22791             : 
   22792             :   // Test path through optimized code.
   22793             :   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   22794             :              "test_get(obj);");
   22795          42 :   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   22796             :   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   22797             :              "test_set(obj);");
   22798          42 :   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   22799             : 
   22800             :   // Cleanup so that closures start out fresh in next check.
   22801             :   CompileRun(
   22802             :       "%DeoptimizeFunction(test_get);"
   22803             :       "%ClearFunctionFeedback(test_get);"
   22804             :       "%DeoptimizeFunction(test_set);"
   22805          42 :       "%ClearFunctionFeedback(test_set);");
   22806          42 : }
   22807             : 
   22808             : 
   22809       28343 : THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   22810           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22811           6 :   LocalContext context;
   22812          12 :   v8::HandleScope scope(context->GetIsolate());
   22813             : 
   22814           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22815           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22816             :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22817             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22818          18 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22819          36 :   CHECK(context->Global()
   22820             :             ->Set(context.local(), v8_str("f"),
   22821             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22822             :             .FromJust());
   22823             : 
   22824             :   printf("Testing positive ...\n");
   22825             :   CompileRun("var obj = new f();");
   22826          30 :   CHECK(templ->HasInstance(
   22827             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22828           6 :   CheckInstanceCheckedAccessors(true);
   22829             : 
   22830             :   printf("Testing negative ...\n");
   22831             :   CompileRun("var obj = {};"
   22832             :              "obj.__proto__ = new f();");
   22833          30 :   CHECK(!templ->HasInstance(
   22834             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22835          12 :   CheckInstanceCheckedAccessors(false);
   22836           6 : }
   22837             : 
   22838          90 : static void EmptyInterceptorGetter(
   22839          90 :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22840             : 
   22841          30 : static void EmptyInterceptorSetter(
   22842             :     Local<Name> name, Local<Value> value,
   22843          30 :     const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22844             : 
   22845       28343 : THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   22846           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22847           6 :   LocalContext context;
   22848          12 :   v8::HandleScope scope(context->GetIsolate());
   22849             : 
   22850           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22851           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22852             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
   22853          12 :       EmptyInterceptorGetter, EmptyInterceptorSetter));
   22854             :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22855             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22856          18 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22857          36 :   CHECK(context->Global()
   22858             :             ->Set(context.local(), v8_str("f"),
   22859             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22860             :             .FromJust());
   22861             : 
   22862             :   printf("Testing positive ...\n");
   22863             :   CompileRun("var obj = new f();");
   22864          30 :   CHECK(templ->HasInstance(
   22865             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22866           6 :   CheckInstanceCheckedAccessors(true);
   22867             : 
   22868             :   printf("Testing negative ...\n");
   22869             :   CompileRun("var obj = {};"
   22870             :              "obj.__proto__ = new f();");
   22871          30 :   CHECK(!templ->HasInstance(
   22872             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22873          12 :   CheckInstanceCheckedAccessors(false);
   22874           6 : }
   22875             : 
   22876             : 
   22877       28343 : THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   22878           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22879           6 :   LocalContext context;
   22880          12 :   v8::HandleScope scope(context->GetIsolate());
   22881             : 
   22882           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22883           6 :   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   22884             :   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   22885             :                      InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
   22886             :                      v8::None,
   22887          18 :                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   22888          36 :   CHECK(context->Global()
   22889             :             ->Set(context.local(), v8_str("f"),
   22890             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22891             :             .FromJust());
   22892             : 
   22893             :   printf("Testing positive ...\n");
   22894             :   CompileRun("var obj = new f();");
   22895          30 :   CHECK(templ->HasInstance(
   22896             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22897           6 :   CheckInstanceCheckedAccessors(true);
   22898             : 
   22899             :   printf("Testing negative ...\n");
   22900             :   CompileRun("var obj = {};"
   22901             :              "obj.__proto__ = new f();");
   22902          30 :   CHECK(!templ->HasInstance(
   22903             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22904           6 :   CheckInstanceCheckedAccessors(false);
   22905             : 
   22906             :   printf("Testing positive with modified prototype chain ...\n");
   22907             :   CompileRun("var obj = new f();"
   22908             :              "var pro = {};"
   22909             :              "pro.__proto__ = obj.__proto__;"
   22910             :              "obj.__proto__ = pro;");
   22911          30 :   CHECK(templ->HasInstance(
   22912             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22913          12 :   CheckInstanceCheckedAccessors(true);
   22914           6 : }
   22915             : 
   22916             : 
   22917       28342 : TEST(TryFinallyMessage) {
   22918           5 :   LocalContext context;
   22919          10 :   v8::HandleScope scope(context->GetIsolate());
   22920             :   {
   22921             :     // Test that the original error message is not lost if there is a
   22922             :     // recursive call into Javascript is done in the finally block, e.g. to
   22923             :     // initialize an IC. (crbug.com/129171)
   22924           5 :     TryCatch try_catch(context->GetIsolate());
   22925             :     const char* trigger_ic =
   22926             :         "try {                      \n"
   22927             :         "  throw new Error('test'); \n"
   22928             :         "} finally {                \n"
   22929             :         "  var x = 0;               \n"
   22930             :         "  x++;                     \n"  // Trigger an IC initialization here.
   22931             :         "}                          \n";
   22932             :     CompileRun(trigger_ic);
   22933           5 :     CHECK(try_catch.HasCaught());
   22934           5 :     Local<Message> message = try_catch.Message();
   22935           5 :     CHECK(!message.IsEmpty());
   22936          10 :     CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   22937             :   }
   22938             : 
   22939             :   {
   22940             :     // Test that the original exception message is indeed overwritten if
   22941             :     // a new error is thrown in the finally block.
   22942           5 :     TryCatch try_catch(context->GetIsolate());
   22943             :     const char* throw_again =
   22944             :         "try {                       \n"
   22945             :         "  throw new Error('test');  \n"
   22946             :         "} finally {                 \n"
   22947             :         "  var x = 0;                \n"
   22948             :         "  x++;                      \n"
   22949             :         "  throw new Error('again'); \n"  // This is the new uncaught error.
   22950             :         "}                           \n";
   22951             :     CompileRun(throw_again);
   22952           5 :     CHECK(try_catch.HasCaught());
   22953           5 :     Local<Message> message = try_catch.Message();
   22954           5 :     CHECK(!message.IsEmpty());
   22955          10 :     CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
   22956           5 :   }
   22957           5 : }
   22958             : 
   22959             : 
   22960          96 : static void Helper137002(bool do_store,
   22961             :                          bool polymorphic,
   22962             :                          bool remove_accessor,
   22963             :                          bool interceptor) {
   22964          96 :   LocalContext context;
   22965          96 :   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   22966          96 :   if (interceptor) {
   22967             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
   22968          48 :                                                             FooSetInterceptor));
   22969             :   } else {
   22970             :     templ->SetAccessor(v8_str("foo"),
   22971             :                        GetterWhichReturns42,
   22972          48 :                        SetterWhichSetsYOnThisTo23);
   22973             :   }
   22974         576 :   CHECK(context->Global()
   22975             :             ->Set(context.local(), v8_str("obj"),
   22976             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22977             :             .FromJust());
   22978             : 
   22979             :   // Turn monomorphic on slow object with native accessor, then turn
   22980             :   // polymorphic, finally optimize to create negative lookup and fail.
   22981             :   CompileRun(do_store ?
   22982             :              "function f(x) { x.foo = void 0; }" :
   22983          96 :              "function f(x) { return x.foo; }");
   22984             :   CompileRun("obj.y = void 0;");
   22985          96 :   if (!interceptor) {
   22986             :     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   22987             :   }
   22988             :   CompileRun("obj.__proto__ = null;"
   22989             :              "f(obj); f(obj); f(obj);");
   22990          96 :   if (polymorphic) {
   22991             :     CompileRun("f({});");
   22992             :   }
   22993             :   CompileRun("obj.y = void 0;"
   22994             :              "%OptimizeFunctionOnNextCall(f);");
   22995          96 :   if (remove_accessor) {
   22996             :     CompileRun("delete obj.foo;");
   22997             :   }
   22998             :   CompileRun("var result = f(obj);");
   22999          96 :   if (do_store) {
   23000             :     CompileRun("result = obj.y;");
   23001             :   }
   23002          96 :   if (remove_accessor && !interceptor) {
   23003         120 :     CHECK(context->Global()
   23004             :               ->Get(context.local(), v8_str("result"))
   23005             :               .ToLocalChecked()
   23006             :               ->IsUndefined());
   23007             :   } else {
   23008         432 :     CHECK_EQ(do_store ? 23 : 42, context->Global()
   23009             :                                      ->Get(context.local(), v8_str("result"))
   23010             :                                      .ToLocalChecked()
   23011             :                                      ->Int32Value(context.local())
   23012             :                                      .FromJust());
   23013          96 :   }
   23014          96 : }
   23015             : 
   23016             : 
   23017       28343 : THREADED_TEST(Regress137002a) {
   23018           6 :   i::FLAG_allow_natives_syntax = true;
   23019           6 :   i::FLAG_compilation_cache = false;
   23020           6 :   v8::HandleScope scope(CcTest::isolate());
   23021         102 :   for (int i = 0; i < 16; i++) {
   23022          96 :     Helper137002(i & 8, i & 4, i & 2, i & 1);
   23023           6 :   }
   23024           6 : }
   23025             : 
   23026             : 
   23027       28343 : THREADED_TEST(Regress137002b) {
   23028           6 :   i::FLAG_allow_natives_syntax = true;
   23029           6 :   LocalContext context;
   23030           6 :   v8::Isolate* isolate = context->GetIsolate();
   23031          12 :   v8::HandleScope scope(isolate);
   23032           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   23033             :   templ->SetAccessor(v8_str("foo"),
   23034             :                      GetterWhichReturns42,
   23035           6 :                      SetterWhichSetsYOnThisTo23);
   23036          36 :   CHECK(context->Global()
   23037             :             ->Set(context.local(), v8_str("obj"),
   23038             :                   templ->NewInstance(context.local()).ToLocalChecked())
   23039             :             .FromJust());
   23040             : 
   23041             :   // Turn monomorphic on slow object with native accessor, then just
   23042             :   // delete the property and fail.
   23043             :   CompileRun("function load(x) { return x.foo; }"
   23044             :              "function store(x) { x.foo = void 0; }"
   23045             :              "function keyed_load(x, key) { return x[key]; }"
   23046             :              // Second version of function has a different source (add void 0)
   23047             :              // so that it does not share code with the first version.  This
   23048             :              // ensures that the ICs are monomorphic.
   23049             :              "function load2(x) { void 0; return x.foo; }"
   23050             :              "function store2(x) { void 0; x.foo = void 0; }"
   23051             :              "function keyed_load2(x, key) { void 0; return x[key]; }"
   23052             : 
   23053             :              "obj.y = void 0;"
   23054             :              "obj.__proto__ = null;"
   23055             :              "var subobj = {};"
   23056             :              "subobj.y = void 0;"
   23057             :              "subobj.__proto__ = obj;"
   23058             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   23059             : 
   23060             :              // Make the ICs monomorphic.
   23061             :              "load(obj); load(obj);"
   23062             :              "load2(subobj); load2(subobj);"
   23063             :              "store(obj); store(obj);"
   23064             :              "store2(subobj); store2(subobj);"
   23065             :              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   23066             :              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   23067             : 
   23068             :              // Actually test the shiny new ICs and better not crash. This
   23069             :              // serves as a regression test for issue 142088 as well.
   23070             :              "load(obj);"
   23071             :              "load2(subobj);"
   23072             :              "store(obj);"
   23073             :              "store2(subobj);"
   23074             :              "keyed_load(obj, 'foo');"
   23075             :              "keyed_load2(subobj, 'foo');"
   23076             : 
   23077             :              // Delete the accessor.  It better not be called any more now.
   23078             :              "delete obj.foo;"
   23079             :              "obj.y = void 0;"
   23080             :              "subobj.y = void 0;"
   23081             : 
   23082             :              "var load_result = load(obj);"
   23083             :              "var load_result2 = load2(subobj);"
   23084             :              "var keyed_load_result = keyed_load(obj, 'foo');"
   23085             :              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   23086             :              "store(obj);"
   23087             :              "store2(subobj);"
   23088             :              "var y_from_obj = obj.y;"
   23089             :              "var y_from_subobj = subobj.y;");
   23090          30 :   CHECK(context->Global()
   23091             :             ->Get(context.local(), v8_str("load_result"))
   23092             :             .ToLocalChecked()
   23093             :             ->IsUndefined());
   23094          30 :   CHECK(context->Global()
   23095             :             ->Get(context.local(), v8_str("load_result2"))
   23096             :             .ToLocalChecked()
   23097             :             ->IsUndefined());
   23098          30 :   CHECK(context->Global()
   23099             :             ->Get(context.local(), v8_str("keyed_load_result"))
   23100             :             .ToLocalChecked()
   23101             :             ->IsUndefined());
   23102          30 :   CHECK(context->Global()
   23103             :             ->Get(context.local(), v8_str("keyed_load_result2"))
   23104             :             .ToLocalChecked()
   23105             :             ->IsUndefined());
   23106          30 :   CHECK(context->Global()
   23107             :             ->Get(context.local(), v8_str("y_from_obj"))
   23108             :             .ToLocalChecked()
   23109             :             ->IsUndefined());
   23110          30 :   CHECK(context->Global()
   23111             :             ->Get(context.local(), v8_str("y_from_subobj"))
   23112             :             .ToLocalChecked()
   23113           6 :             ->IsUndefined());
   23114           6 : }
   23115             : 
   23116             : 
   23117       28343 : THREADED_TEST(Regress142088) {
   23118           6 :   i::FLAG_allow_natives_syntax = true;
   23119           6 :   LocalContext context;
   23120           6 :   v8::Isolate* isolate = context->GetIsolate();
   23121          12 :   v8::HandleScope scope(isolate);
   23122           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   23123             :   templ->SetAccessor(v8_str("foo"),
   23124             :                      GetterWhichReturns42,
   23125           6 :                      SetterWhichSetsYOnThisTo23);
   23126          36 :   CHECK(context->Global()
   23127             :             ->Set(context.local(), v8_str("obj"),
   23128             :                   templ->NewInstance(context.local()).ToLocalChecked())
   23129             :             .FromJust());
   23130             : 
   23131             :   CompileRun("function load(x) { return x.foo; }"
   23132             :              "var o = Object.create(obj);"
   23133             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   23134           6 :              "load(o); load(o); load(o); load(o);");
   23135           6 : }
   23136             : 
   23137             : 
   23138       28343 : THREADED_TEST(Regress137496) {
   23139           6 :   i::FLAG_expose_gc = true;
   23140           6 :   LocalContext context;
   23141          12 :   v8::HandleScope scope(context->GetIsolate());
   23142             : 
   23143             :   // Compile a try-finally clause where the finally block causes a GC
   23144             :   // while there still is a message pending for external reporting.
   23145          12 :   TryCatch try_catch(context->GetIsolate());
   23146           6 :   try_catch.SetVerbose(true);
   23147             :   CompileRun("try { throw new Error(); } finally { gc(); }");
   23148          12 :   CHECK(try_catch.HasCaught());
   23149           6 : }
   23150             : 
   23151             : 
   23152       28343 : THREADED_TEST(Regress157124) {
   23153           6 :   LocalContext context;
   23154           6 :   v8::Isolate* isolate = context->GetIsolate();
   23155          12 :   v8::HandleScope scope(isolate);
   23156           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   23157          12 :   Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   23158           6 :   obj->GetIdentityHash();
   23159             :   obj->DeletePrivate(context.local(),
   23160           6 :                      v8::Private::ForApi(isolate, v8_str("Bug")))
   23161          18 :       .FromJust();
   23162           6 : }
   23163             : 
   23164             : 
   23165       28343 : THREADED_TEST(Regress2535) {
   23166           6 :   LocalContext context;
   23167          12 :   v8::HandleScope scope(context->GetIsolate());
   23168             :   Local<Value> set_value = CompileRun("new Set();");
   23169             :   Local<Object> set_object(Local<Object>::Cast(set_value));
   23170           6 :   CHECK_EQ(0, set_object->InternalFieldCount());
   23171             :   Local<Value> map_value = CompileRun("new Map();");
   23172             :   Local<Object> map_object(Local<Object>::Cast(map_value));
   23173          12 :   CHECK_EQ(0, map_object->InternalFieldCount());
   23174           6 : }
   23175             : 
   23176             : 
   23177       28343 : THREADED_TEST(Regress2746) {
   23178           6 :   LocalContext context;
   23179           6 :   v8::Isolate* isolate = context->GetIsolate();
   23180          12 :   v8::HandleScope scope(isolate);
   23181           6 :   Local<Object> obj = Object::New(isolate);
   23182           6 :   Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
   23183          12 :   CHECK(
   23184             :       obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
   23185           6 :   Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
   23186           6 :   CHECK(!value.IsEmpty());
   23187          12 :   CHECK(value->IsUndefined());
   23188           6 : }
   23189             : 
   23190             : 
   23191       28343 : THREADED_TEST(Regress260106) {
   23192           6 :   LocalContext context;
   23193           6 :   v8::Isolate* isolate = context->GetIsolate();
   23194          12 :   v8::HandleScope scope(isolate);
   23195             :   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   23196           6 :                                                         DummyCallHandler);
   23197             :   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   23198             :   Local<Function> function =
   23199          12 :       templ->GetFunction(context.local()).ToLocalChecked();
   23200           6 :   CHECK(!function.IsEmpty());
   23201          12 :   CHECK(function->IsFunction());
   23202           6 : }
   23203             : 
   23204       28343 : THREADED_TEST(JSONParseObject) {
   23205           6 :   LocalContext context;
   23206          12 :   HandleScope scope(context->GetIsolate());
   23207             :   Local<Value> obj =
   23208          12 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   23209           6 :   Local<Object> global = context->Global();
   23210          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   23211          12 :   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   23212           6 : }
   23213             : 
   23214       28343 : THREADED_TEST(JSONParseNumber) {
   23215           6 :   LocalContext context;
   23216          12 :   HandleScope scope(context->GetIsolate());
   23217             :   Local<Value> obj =
   23218          12 :       v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
   23219           6 :   Local<Object> global = context->Global();
   23220          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   23221          12 :   ExpectString("JSON.stringify(obj)", "42");
   23222           6 : }
   23223             : 
   23224             : namespace {
   23225          42 : void TestJSONParseArray(Local<Context> context, const char* input_str,
   23226             :                         const char* expected_output_str,
   23227             :                         i::ElementsKind expected_elements_kind) {
   23228             :   Local<Value> obj =
   23229          42 :       v8::JSON::Parse(context, v8_str(input_str)).ToLocalChecked();
   23230             : 
   23231             :   i::Handle<i::JSArray> a =
   23232          42 :       i::Handle<i::JSArray>::cast(v8::Utils::OpenHandle(*obj));
   23233          42 :   CHECK_EQ(expected_elements_kind, a->GetElementsKind());
   23234             : 
   23235          42 :   Local<Object> global = context->Global();
   23236         126 :   global->Set(context, v8_str("obj"), obj).FromJust();
   23237          42 :   ExpectString("JSON.stringify(obj)", expected_output_str);
   23238          42 : }
   23239             : }  // namespace
   23240             : 
   23241       28343 : THREADED_TEST(JSONParseArray) {
   23242           6 :   LocalContext context;
   23243          12 :   HandleScope scope(context->GetIsolate());
   23244             : 
   23245             :   TestJSONParseArray(context.local(), "[0, 1, 2]", "[0,1,2]",
   23246           6 :                      i::PACKED_SMI_ELEMENTS);
   23247             :   TestJSONParseArray(context.local(), "[0, 1.2, 2]", "[0,1.2,2]",
   23248           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   23249             :   TestJSONParseArray(context.local(), "[0.2, 1, 2]", "[0.2,1,2]",
   23250           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   23251             :   TestJSONParseArray(context.local(), "[0, \"a\", 2]", "[0,\"a\",2]",
   23252           6 :                      i::PACKED_ELEMENTS);
   23253             :   TestJSONParseArray(context.local(), "[\"a\", 1, 2]", "[\"a\",1,2]",
   23254           6 :                      i::PACKED_ELEMENTS);
   23255             :   TestJSONParseArray(context.local(), "[\"a\", 1.2, 2]", "[\"a\",1.2,2]",
   23256           6 :                      i::PACKED_ELEMENTS);
   23257             :   TestJSONParseArray(context.local(), "[0, 1.2, \"a\"]", "[0,1.2,\"a\"]",
   23258          12 :                      i::PACKED_ELEMENTS);
   23259           6 : }
   23260             : 
   23261       28343 : THREADED_TEST(JSONStringifyObject) {
   23262           6 :   LocalContext context;
   23263          12 :   HandleScope scope(context->GetIsolate());
   23264             :   Local<Value> value =
   23265           6 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   23266           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   23267           6 :   Local<Object> global = context->Global();
   23268          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   23269             :   Local<String> json =
   23270          12 :       v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
   23271          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   23272          12 :   ExpectString("JSON.stringify(obj)", *utf8);
   23273           6 : }
   23274             : 
   23275       28343 : THREADED_TEST(JSONStringifyObjectWithGap) {
   23276           6 :   LocalContext context;
   23277          12 :   HandleScope scope(context->GetIsolate());
   23278             :   Local<Value> value =
   23279           6 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   23280           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   23281           6 :   Local<Object> global = context->Global();
   23282          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   23283             :   Local<String> json =
   23284          18 :       v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
   23285          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   23286          12 :   ExpectString("JSON.stringify(obj, null,  '*')", *utf8);
   23287           6 : }
   23288             : 
   23289             : #if V8_OS_POSIX
   23290             : class ThreadInterruptTest {
   23291             :  public:
   23292           6 :   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   23293           6 :   ~ThreadInterruptTest() = default;
   23294             : 
   23295           6 :   void RunTest() {
   23296             :     InterruptThread i_thread(this);
   23297           6 :     i_thread.Start();
   23298             : 
   23299           6 :     sem_.Wait();
   23300           6 :     CHECK_EQ(kExpectedValue, sem_value_);
   23301           6 :   }
   23302             : 
   23303             :  private:
   23304             :   static const int kExpectedValue = 1;
   23305             : 
   23306           6 :   class InterruptThread : public v8::base::Thread {
   23307             :    public:
   23308             :     explicit InterruptThread(ThreadInterruptTest* test)
   23309           6 :         : Thread(Options("InterruptThread")), test_(test) {}
   23310             : 
   23311           6 :     void Run() override {
   23312             :       struct sigaction action;
   23313             : 
   23314             :       // Ensure that we'll enter waiting condition
   23315           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   23316             : 
   23317             :       // Setup signal handler
   23318             :       memset(&action, 0, sizeof(action));
   23319           6 :       action.sa_handler = SignalHandler;
   23320           6 :       sigaction(SIGCHLD, &action, nullptr);
   23321             : 
   23322             :       // Send signal
   23323           6 :       kill(getpid(), SIGCHLD);
   23324             : 
   23325             :       // Ensure that if wait has returned because of error
   23326           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   23327             : 
   23328             :       // Set value and signal semaphore
   23329           6 :       test_->sem_value_ = 1;
   23330           6 :       test_->sem_.Signal();
   23331           6 :     }
   23332             : 
   23333           6 :     static void SignalHandler(int signal) {
   23334           6 :     }
   23335             : 
   23336             :    private:
   23337             :      ThreadInterruptTest* test_;
   23338             :   };
   23339             : 
   23340             :   v8::base::Semaphore sem_;
   23341             :   volatile int sem_value_;
   23342             : };
   23343             : 
   23344             : 
   23345       28343 : THREADED_TEST(SemaphoreInterruption) {
   23346          12 :   ThreadInterruptTest().RunTest();
   23347           6 : }
   23348             : 
   23349             : 
   23350             : #endif  // V8_OS_POSIX
   23351             : 
   23352             : 
   23353           0 : void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   23354           0 :   UNREACHABLE();
   23355             : }
   23356             : 
   23357             : 
   23358       28342 : TEST(JSONStringifyAccessCheck) {
   23359           5 :   v8::V8::Initialize();
   23360           5 :   v8::Isolate* isolate = CcTest::isolate();
   23361           5 :   v8::HandleScope scope(isolate);
   23362             : 
   23363             :   // Create an ObjectTemplate for global objects and install access
   23364             :   // check callbacks that will block access.
   23365             :   v8::Local<v8::ObjectTemplate> global_template =
   23366           5 :       v8::ObjectTemplate::New(isolate);
   23367           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   23368             : 
   23369             :   // Create a context and set an x property on it's global object.
   23370          10 :   LocalContext context0(nullptr, global_template);
   23371           5 :   v8::Local<v8::Object> global0 = context0->Global();
   23372          15 :   global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
   23373           5 :   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   23374             : 
   23375          15 :   for (int i = 0; i < 2; i++) {
   23376          10 :     if (i == 1) {
   23377             :       // Install a toJSON function on the second run.
   23378             :       v8::Local<v8::FunctionTemplate> toJSON =
   23379           5 :           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   23380             : 
   23381             :       global0->Set(context0.local(), v8_str("toJSON"),
   23382          25 :                    toJSON->GetFunction(context0.local()).ToLocalChecked())
   23383          10 :           .FromJust();
   23384             :     }
   23385             :     // Create a context with a different security token so that the
   23386             :     // failed access check callback will be called on each access.
   23387          10 :     LocalContext context1(nullptr, global_template);
   23388          50 :     CHECK(context1->Global()
   23389             :               ->Set(context1.local(), v8_str("other"), global0)
   23390             :               .FromJust());
   23391             : 
   23392          10 :     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   23393          10 :     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   23394          10 :     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   23395          15 :   }
   23396           5 : }
   23397             : 
   23398             : 
   23399             : bool access_check_fail_thrown = false;
   23400             : bool catch_callback_called = false;
   23401             : 
   23402             : 
   23403             : // Failed access check callback that performs a GC on each invocation.
   23404          80 : void FailedAccessCheckThrows(Local<v8::Object> target,
   23405             :                              v8::AccessType type,
   23406             :                              Local<v8::Value> data) {
   23407          80 :   access_check_fail_thrown = true;
   23408          80 :   i::PrintF("Access check failed. Error thrown.\n");
   23409             :   CcTest::isolate()->ThrowException(
   23410          80 :       v8::Exception::Error(v8_str("cross context")));
   23411          80 : }
   23412             : 
   23413             : 
   23414         300 : void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   23415         300 :   for (int i = 0; i < args.Length(); i++) {
   23416          75 :     i::PrintF("%s\n", *String::Utf8Value(args.GetIsolate(), args[i]));
   23417             :   }
   23418          75 :   catch_callback_called = true;
   23419          75 : }
   23420             : 
   23421             : 
   23422           5 : void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   23423           5 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   23424          20 :   CHECK(
   23425             :       args[0]
   23426             :           ->ToObject(context)
   23427             :           .ToLocalChecked()
   23428             :           ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
   23429             :           .IsNothing());
   23430           5 : }
   23431             : 
   23432             : 
   23433          75 : void CheckCorrectThrow(const char* script) {
   23434             :   // Test that the script, when wrapped into a try-catch, triggers the catch
   23435             :   // clause due to failed access check throwing an exception.
   23436             :   // The subsequent try-catch should run without any exception.
   23437          75 :   access_check_fail_thrown = false;
   23438          75 :   catch_callback_called = false;
   23439             :   i::ScopedVector<char> source(1024);
   23440          75 :   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   23441             :   CompileRun(source.start());
   23442          75 :   CHECK(access_check_fail_thrown);
   23443          75 :   CHECK(catch_callback_called);
   23444             : 
   23445          75 :   access_check_fail_thrown = false;
   23446          75 :   catch_callback_called = false;
   23447             :   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   23448          75 :   CHECK(!access_check_fail_thrown);
   23449          75 :   CHECK(!catch_callback_called);
   23450          75 : }
   23451             : 
   23452             : 
   23453       28342 : TEST(AccessCheckThrows) {
   23454           5 :   i::FLAG_allow_natives_syntax = true;
   23455           5 :   v8::V8::Initialize();
   23456           5 :   v8::Isolate* isolate = CcTest::isolate();
   23457           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   23458           5 :   v8::HandleScope scope(isolate);
   23459             : 
   23460             :   // Create an ObjectTemplate for global objects and install access
   23461             :   // check callbacks that will block access.
   23462             :   v8::Local<v8::ObjectTemplate> global_template =
   23463           5 :       v8::ObjectTemplate::New(isolate);
   23464           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   23465             : 
   23466             :   // Create a context and set an x property on it's global object.
   23467          10 :   LocalContext context0(nullptr, global_template);
   23468           5 :   v8::Local<v8::Object> global0 = context0->Global();
   23469          15 :   CHECK(global0->Set(context0.local(), v8_str("x"), global0).FromJust());
   23470             : 
   23471             :   // Create a context with a different security token so that the
   23472             :   // failed access check callback will be called on each access.
   23473          10 :   LocalContext context1(nullptr, global_template);
   23474          25 :   CHECK(context1->Global()
   23475             :             ->Set(context1.local(), v8_str("other"), global0)
   23476             :             .FromJust());
   23477             : 
   23478             :   v8::Local<v8::FunctionTemplate> catcher_fun =
   23479           5 :       v8::FunctionTemplate::New(isolate, CatcherCallback);
   23480          35 :   CHECK(context1->Global()
   23481             :             ->Set(context1.local(), v8_str("catcher"),
   23482             :                   catcher_fun->GetFunction(context1.local()).ToLocalChecked())
   23483             :             .FromJust());
   23484             : 
   23485             :   v8::Local<v8::FunctionTemplate> has_own_property_fun =
   23486           5 :       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   23487          35 :   CHECK(context1->Global()
   23488             :             ->Set(context1.local(), v8_str("has_own_property"),
   23489             :                   has_own_property_fun->GetFunction(context1.local())
   23490             :                       .ToLocalChecked())
   23491             :             .FromJust());
   23492             : 
   23493             :   {
   23494           5 :     v8::TryCatch try_catch(isolate);
   23495           5 :     access_check_fail_thrown = false;
   23496             :     CompileRun("other.x;");
   23497           5 :     CHECK(access_check_fail_thrown);
   23498           5 :     CHECK(try_catch.HasCaught());
   23499             :   }
   23500             : 
   23501           5 :   CheckCorrectThrow("other.x");
   23502           5 :   CheckCorrectThrow("other[1]");
   23503           5 :   CheckCorrectThrow("JSON.stringify(other)");
   23504           5 :   CheckCorrectThrow("has_own_property(other, 'x')");
   23505           5 :   CheckCorrectThrow("%GetProperty(other, 'x')");
   23506           5 :   CheckCorrectThrow("%SetKeyedProperty(other, 'x', 'foo', 0)");
   23507           5 :   CheckCorrectThrow("%SetNamedProperty(other, 'y', 'foo', 1)");
   23508             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kSloppy) == 0);
   23509             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kStrict) == 1);
   23510           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");  // 0 == SLOPPY
   23511           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 1)");  // 1 == STRICT
   23512           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   23513           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 1)");
   23514           5 :   CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
   23515           5 :   CheckCorrectThrow("%HasProperty(other, 'x')");
   23516           5 :   CheckCorrectThrow("Object.prototype.propertyIsEnumerable(other, 'x')");
   23517             :   // PROPERTY_ATTRIBUTES_NONE = 0
   23518             :   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   23519           5 :                         "other, 'x', null, null, 1)");
   23520             : 
   23521             :   // Reset the failed access check callback so it does not influence
   23522             :   // the other tests.
   23523          10 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   23524           5 : }
   23525             : 
   23526             : class RequestInterruptTestBase {
   23527             :  public:
   23528          35 :   RequestInterruptTestBase()
   23529             :       : env_(),
   23530          35 :         isolate_(env_->GetIsolate()),
   23531             :         sem_(0),
   23532             :         warmup_(20000),
   23533         105 :         should_continue_(true) {
   23534          35 :   }
   23535             : 
   23536          35 :   virtual ~RequestInterruptTestBase() = default;
   23537             : 
   23538             :   virtual void StartInterruptThread() = 0;
   23539             : 
   23540             :   virtual void TestBody() = 0;
   23541             : 
   23542          70 :   void RunTest() {
   23543          35 :     StartInterruptThread();
   23544             : 
   23545          35 :     v8::HandleScope handle_scope(isolate_);
   23546             : 
   23547          35 :     TestBody();
   23548             : 
   23549             :     // Verify we arrived here because interruptor was called
   23550             :     // not due to a bug causing us to exit the loop too early.
   23551          35 :     CHECK(!should_continue());
   23552          35 :   }
   23553             : 
   23554             :   void WakeUpInterruptor() {
   23555          35 :     sem_.Signal();
   23556             :   }
   23557             : 
   23558             :   bool should_continue() const { return should_continue_; }
   23559             : 
   23560      867215 :   bool ShouldContinue() {
   23561      867215 :     if (warmup_ > 0) {
   23562      600000 :       if (--warmup_ == 0) {
   23563             :         WakeUpInterruptor();
   23564             :       }
   23565             :     }
   23566             : 
   23567      867215 :     return should_continue_;
   23568             :   }
   23569             : 
   23570      759555 :   static void ShouldContinueCallback(
   23571     1519110 :       const v8::FunctionCallbackInfo<Value>& info) {
   23572             :     RequestInterruptTestBase* test =
   23573             :         reinterpret_cast<RequestInterruptTestBase*>(
   23574      759555 :             info.Data().As<v8::External>()->Value());
   23575      759555 :     info.GetReturnValue().Set(test->ShouldContinue());
   23576      759555 :   }
   23577             : 
   23578             :   LocalContext env_;
   23579             :   v8::Isolate* isolate_;
   23580             :   v8::base::Semaphore sem_;
   23581             :   int warmup_;
   23582             :   bool should_continue_;
   23583             : };
   23584             : 
   23585             : 
   23586          60 : class RequestInterruptTestBaseWithSimpleInterrupt
   23587             :     : public RequestInterruptTestBase {
   23588             :  public:
   23589          60 :   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   23590             : 
   23591          30 :   void StartInterruptThread() override { i_thread.Start(); }
   23592             : 
   23593             :  private:
   23594          30 :   class InterruptThread : public v8::base::Thread {
   23595             :    public:
   23596             :     explicit InterruptThread(RequestInterruptTestBase* test)
   23597          30 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   23598             : 
   23599          30 :     void Run() override {
   23600          30 :       test_->sem_.Wait();
   23601          30 :       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   23602          30 :     }
   23603             : 
   23604          30 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   23605             :       reinterpret_cast<RequestInterruptTestBase*>(data)->
   23606          30 :           should_continue_ = false;
   23607          30 :     }
   23608             : 
   23609             :    private:
   23610             :      RequestInterruptTestBase* test_;
   23611             :   };
   23612             : 
   23613             :   InterruptThread i_thread;
   23614             : };
   23615             : 
   23616             : 
   23617          10 : class RequestInterruptTestWithFunctionCall
   23618             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23619             :  public:
   23620           5 :   void TestBody() override {
   23621             :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23622          15 :                                          v8::External::New(isolate_, this))
   23623           5 :                                .ToLocalChecked();
   23624          25 :     CHECK(env_->Global()
   23625             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23626             :               .FromJust());
   23627             : 
   23628             :     CompileRun("while (ShouldContinue()) { }");
   23629           5 :   }
   23630             : };
   23631             : 
   23632             : 
   23633          10 : class RequestInterruptTestWithMethodCall
   23634             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23635             :  public:
   23636           5 :   void TestBody() override {
   23637           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23638           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23639             :     proto->Set(v8_str("shouldContinue"),
   23640             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23641          20 :                                      v8::External::New(isolate_, this)));
   23642          30 :     CHECK(env_->Global()
   23643             :               ->Set(env_.local(), v8_str("Klass"),
   23644             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23645             :               .FromJust());
   23646             : 
   23647             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23648           5 :   }
   23649             : };
   23650             : 
   23651             : 
   23652          10 : class RequestInterruptTestWithAccessor
   23653             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23654             :  public:
   23655           5 :   void TestBody() override {
   23656           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23657           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23658             :     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   23659          15 :         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   23660          30 :     CHECK(env_->Global()
   23661             :               ->Set(env_.local(), v8_str("Klass"),
   23662             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23663             :               .FromJust());
   23664             : 
   23665             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   23666           5 :   }
   23667             : };
   23668             : 
   23669             : 
   23670          10 : class RequestInterruptTestWithNativeAccessor
   23671             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23672             :  public:
   23673           5 :   void TestBody() override {
   23674           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23675          10 :     t->InstanceTemplate()->SetNativeDataProperty(
   23676             :         v8_str("shouldContinue"), &ShouldContinueNativeGetter, nullptr,
   23677          20 :         v8::External::New(isolate_, this));
   23678          30 :     CHECK(env_->Global()
   23679             :               ->Set(env_.local(), v8_str("Klass"),
   23680             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23681             :               .FromJust());
   23682             : 
   23683             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   23684           5 :   }
   23685             : 
   23686             :  private:
   23687      107660 :   static void ShouldContinueNativeGetter(
   23688             :       Local<String> property,
   23689             :       const v8::PropertyCallbackInfo<v8::Value>& info) {
   23690             :     RequestInterruptTestBase* test =
   23691             :         reinterpret_cast<RequestInterruptTestBase*>(
   23692      107660 :             info.Data().As<v8::External>()->Value());
   23693      107660 :     info.GetReturnValue().Set(test->ShouldContinue());
   23694      107660 :   }
   23695             : };
   23696             : 
   23697             : 
   23698          10 : class RequestInterruptTestWithMethodCallAndInterceptor
   23699             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23700             :  public:
   23701           5 :   void TestBody() override {
   23702           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23703           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23704             :     proto->Set(v8_str("shouldContinue"),
   23705             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23706          20 :                                      v8::External::New(isolate_, this)));
   23707           5 :     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   23708             :     instance_template->SetHandler(
   23709           5 :         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
   23710             : 
   23711          30 :     CHECK(env_->Global()
   23712             :               ->Set(env_.local(), v8_str("Klass"),
   23713             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23714             :               .FromJust());
   23715             : 
   23716             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23717           5 :   }
   23718             : 
   23719             :  private:
   23720      100031 :   static void EmptyInterceptor(
   23721      100031 :       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   23722             : };
   23723             : 
   23724             : 
   23725          10 : class RequestInterruptTestWithMathAbs
   23726             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23727             :  public:
   23728           5 :   void TestBody() override {
   23729             :     env_->Global()
   23730             :         ->Set(env_.local(), v8_str("WakeUpInterruptor"),
   23731             :               Function::New(env_.local(), WakeUpInterruptorCallback,
   23732          15 :                             v8::External::New(isolate_, this))
   23733          25 :                   .ToLocalChecked())
   23734          10 :         .FromJust();
   23735             : 
   23736             :     env_->Global()
   23737             :         ->Set(env_.local(), v8_str("ShouldContinue"),
   23738             :               Function::New(env_.local(), ShouldContinueCallback,
   23739          15 :                             v8::External::New(isolate_, this))
   23740          25 :                   .ToLocalChecked())
   23741          10 :         .FromJust();
   23742             : 
   23743           5 :     i::FLAG_allow_natives_syntax = true;
   23744             :     CompileRun("function loopish(o) {"
   23745             :                "  var pre = 10;"
   23746             :                "  while (o.abs(1) > 0) {"
   23747             :                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   23748             :                "    if (pre > 0) {"
   23749             :                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   23750             :                "    }"
   23751             :                "  }"
   23752             :                "}"
   23753             :                "var i = 50;"
   23754             :                "var obj = {abs: function () { return i-- }, x: null};"
   23755             :                "delete obj.x;"
   23756             :                "loopish(obj);"
   23757             :                "%OptimizeFunctionOnNextCall(loopish);"
   23758             :                "loopish(Math);");
   23759             : 
   23760           5 :     i::FLAG_allow_natives_syntax = false;
   23761           5 :   }
   23762             : 
   23763             :  private:
   23764          10 :   static void WakeUpInterruptorCallback(
   23765          15 :       const v8::FunctionCallbackInfo<Value>& info) {
   23766          10 :     if (!info[0]->BooleanValue(info.GetIsolate())) {
   23767          10 :       return;
   23768             :     }
   23769             : 
   23770             :     RequestInterruptTestBase* test =
   23771             :         reinterpret_cast<RequestInterruptTestBase*>(
   23772           5 :             info.Data().As<v8::External>()->Value());
   23773             :     test->WakeUpInterruptor();
   23774             :   }
   23775             : 
   23776       56310 :   static void ShouldContinueCallback(
   23777      112620 :       const v8::FunctionCallbackInfo<Value>& info) {
   23778       56310 :     RequestInterruptTestBase* test =
   23779             :         reinterpret_cast<RequestInterruptTestBase*>(
   23780       56310 :             info.Data().As<v8::External>()->Value());
   23781             :     info.GetReturnValue().Set(test->should_continue());
   23782       56310 :   }
   23783             : };
   23784             : 
   23785             : 
   23786       28342 : TEST(RequestInterruptTestWithFunctionCall) {
   23787          15 :   RequestInterruptTestWithFunctionCall().RunTest();
   23788           5 : }
   23789             : 
   23790             : 
   23791       28342 : TEST(RequestInterruptTestWithMethodCall) {
   23792          15 :   RequestInterruptTestWithMethodCall().RunTest();
   23793           5 : }
   23794             : 
   23795             : 
   23796       28342 : TEST(RequestInterruptTestWithAccessor) {
   23797          15 :   RequestInterruptTestWithAccessor().RunTest();
   23798           5 : }
   23799             : 
   23800             : 
   23801       28342 : TEST(RequestInterruptTestWithNativeAccessor) {
   23802          15 :   RequestInterruptTestWithNativeAccessor().RunTest();
   23803           5 : }
   23804             : 
   23805             : 
   23806       28342 : TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   23807          15 :   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   23808           5 : }
   23809             : 
   23810             : 
   23811       28342 : TEST(RequestInterruptTestWithMathAbs) {
   23812          15 :   RequestInterruptTestWithMathAbs().RunTest();
   23813           5 : }
   23814             : 
   23815             : 
   23816          10 : class RequestMultipleInterrupts : public RequestInterruptTestBase {
   23817             :  public:
   23818          10 :   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
   23819             : 
   23820           5 :   void StartInterruptThread() override { i_thread.Start(); }
   23821             : 
   23822           5 :   void TestBody() override {
   23823             :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23824          15 :                                          v8::External::New(isolate_, this))
   23825           5 :                                .ToLocalChecked();
   23826          25 :     CHECK(env_->Global()
   23827             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23828             :               .FromJust());
   23829             : 
   23830             :     CompileRun("while (ShouldContinue()) { }");
   23831           5 :   }
   23832             : 
   23833             :  private:
   23834           5 :   class InterruptThread : public v8::base::Thread {
   23835             :    public:
   23836             :     enum { NUM_INTERRUPTS = 10 };
   23837             :     explicit InterruptThread(RequestMultipleInterrupts* test)
   23838           5 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   23839             : 
   23840           5 :     void Run() override {
   23841           5 :       test_->sem_.Wait();
   23842          55 :       for (int i = 0; i < NUM_INTERRUPTS; i++) {
   23843          50 :         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   23844             :       }
   23845           5 :     }
   23846             : 
   23847          50 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   23848             :       RequestMultipleInterrupts* test =
   23849             :           reinterpret_cast<RequestMultipleInterrupts*>(data);
   23850          50 :       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
   23851          50 :     }
   23852             : 
   23853             :    private:
   23854             :     RequestMultipleInterrupts* test_;
   23855             :   };
   23856             : 
   23857             :   InterruptThread i_thread;
   23858             :   int counter_;
   23859             : };
   23860             : 
   23861             : 
   23862       28342 : TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
   23863             : 
   23864             : 
   23865             : static bool interrupt_was_called = false;
   23866             : 
   23867             : 
   23868           5 : void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
   23869           5 :   interrupt_was_called = true;
   23870           5 : }
   23871             : 
   23872             : 
   23873       28342 : TEST(RequestInterruptSmallScripts) {
   23874           5 :   LocalContext env;
   23875           5 :   v8::Isolate* isolate = CcTest::isolate();
   23876          10 :   v8::HandleScope scope(isolate);
   23877             : 
   23878           5 :   interrupt_was_called = false;
   23879           5 :   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, nullptr);
   23880             :   CompileRun("(function(x){return x;})(1);");
   23881          10 :   CHECK(interrupt_was_called);
   23882           5 : }
   23883             : 
   23884             : 
   23885             : static Local<Value> function_new_expected_env;
   23886          24 : static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   23887          36 :   CHECK(
   23888             :       function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
   23889             :                                         info.Data())
   23890             :           .FromJust());
   23891             :   info.GetReturnValue().Set(17);
   23892          12 : }
   23893             : 
   23894             : 
   23895       28343 : THREADED_TEST(FunctionNew) {
   23896           6 :   LocalContext env;
   23897           6 :   v8::Isolate* isolate = env->GetIsolate();
   23898          12 :   v8::HandleScope scope(isolate);
   23899           6 :   Local<Object> data = v8::Object::New(isolate);
   23900           6 :   function_new_expected_env = data;
   23901             :   Local<Function> func =
   23902          12 :       Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
   23903          30 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   23904           6 :   Local<Value> result = CompileRun("func();");
   23905          18 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
   23906             :   // Serial number should be invalid => should not be cached.
   23907             :   auto serial_number =
   23908             :       i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
   23909          18 :                        ->shared()
   23910          12 :                        ->get_api_func_data()
   23911          12 :                        ->serial_number())
   23912             :           ->value();
   23913           6 :   CHECK_EQ(i::FunctionTemplateInfo::kInvalidSerialNumber, serial_number);
   23914             : 
   23915             :   // Verify that each Function::New creates a new function instance
   23916           6 :   Local<Object> data2 = v8::Object::New(isolate);
   23917           6 :   function_new_expected_env = data2;
   23918             :   Local<Function> func2 =
   23919          12 :       Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
   23920           6 :   CHECK(!func2->IsNull());
   23921          12 :   CHECK(!func->Equals(env.local(), func2).FromJust());
   23922          30 :   CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   23923           6 :   Local<Value> result2 = CompileRun("func2();");
   23924          24 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
   23925           6 : }
   23926             : 
   23927             : namespace {
   23928             : 
   23929             : void Verify(v8::Isolate* isolate, Local<v8::Object> obj) {
   23930             : #if VERIFY_HEAP
   23931             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   23932             :   i::Handle<i::JSReceiver> i_obj = v8::Utils::OpenHandle(*obj);
   23933             :   i_obj->ObjectVerify(i_isolate);
   23934             : #endif
   23935             : }
   23936             : 
   23937             : }  // namespace
   23938             : 
   23939       28343 : THREADED_TEST(ObjectNew) {
   23940           6 :   LocalContext env;
   23941           6 :   v8::Isolate* isolate = env->GetIsolate();
   23942          12 :   v8::HandleScope scope(isolate);
   23943             :   {
   23944             :     // Verify that Object::New(null) produces an object with a null
   23945             :     // [[Prototype]].
   23946             :     Local<v8::Object> obj =
   23947           6 :         v8::Object::New(isolate, v8::Null(isolate), nullptr, nullptr, 0);
   23948          12 :     CHECK(obj->GetPrototype()->IsNull());
   23949             :     Verify(isolate, obj);
   23950           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23951           6 :     CHECK_EQ(0, keys->Length());
   23952             :   }
   23953             :   {
   23954             :     // Verify that Object::New(proto) produces an object with
   23955             :     // proto as it's [[Prototype]].
   23956           6 :     Local<v8::Object> proto = v8::Object::New(isolate);
   23957             :     Local<v8::Object> obj =
   23958           6 :         v8::Object::New(isolate, proto, nullptr, nullptr, 0);
   23959             :     Verify(isolate, obj);
   23960          12 :     CHECK(obj->GetPrototype()->SameValue(proto));
   23961             :   }
   23962             :   {
   23963             :     // Verify that the properties are installed correctly.
   23964          18 :     Local<v8::Name> names[3] = {v8_str("a"), v8_str("b"), v8_str("c")};
   23965           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23966             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23967           6 :                                             values, arraysize(values));
   23968             :     Verify(isolate, obj);
   23969           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23970           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23971          18 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23972          54 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23973          54 :       CHECK(values[i]->SameValue(
   23974             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23975             :     }
   23976             :   }
   23977             :   {
   23978             :     // Same as above, but with non-null prototype.
   23979           6 :     Local<v8::Object> proto = v8::Object::New(isolate);
   23980          18 :     Local<v8::Name> names[3] = {v8_str("x"), v8_str("y"), v8_str("z")};
   23981           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23982             :     Local<v8::Object> obj =
   23983           6 :         v8::Object::New(isolate, proto, names, values, arraysize(values));
   23984          12 :     CHECK(obj->GetPrototype()->SameValue(proto));
   23985             :     Verify(isolate, obj);
   23986           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23987           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23988          18 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23989          54 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23990          54 :       CHECK(values[i]->SameValue(
   23991             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23992             :     }
   23993             :   }
   23994             :   {
   23995             :     // This has to work with duplicate names too.
   23996          18 :     Local<v8::Name> names[3] = {v8_str("a"), v8_str("a"), v8_str("a")};
   23997           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23998             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23999           6 :                                             values, arraysize(values));
   24000             :     Verify(isolate, obj);
   24001           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   24002           6 :     CHECK_EQ(1, keys->Length());
   24003          18 :     CHECK(v8_str("a")->SameValue(keys->Get(env.local(), 0).ToLocalChecked()));
   24004          24 :     CHECK(v8_num(3)->SameValue(
   24005             :         obj->Get(env.local(), v8_str("a")).ToLocalChecked()));
   24006             :   }
   24007             :   {
   24008             :     // This has to work with array indices too.
   24009          12 :     Local<v8::Name> names[2] = {v8_str("0"), v8_str("1")};
   24010           6 :     Local<v8::Value> values[2] = {v8_num(0), v8_num(1)};
   24011             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   24012           6 :                                             values, arraysize(values));
   24013             :     Verify(isolate, obj);
   24014           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   24015           6 :     CHECK_EQ(arraysize(names), keys->Length());
   24016          12 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   24017          36 :       CHECK(v8::Number::New(isolate, i)
   24018             :                 ->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   24019          36 :       CHECK(values[i]->SameValue(obj->Get(env.local(), i).ToLocalChecked()));
   24020             :     }
   24021             :   }
   24022             :   {
   24023             :     // This has to work with mixed array indices / property names too.
   24024          12 :     Local<v8::Name> names[2] = {v8_str("0"), v8_str("x")};
   24025           6 :     Local<v8::Value> values[2] = {v8_num(42), v8_num(24)};
   24026             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   24027           6 :                                             values, arraysize(values));
   24028             :     Verify(isolate, obj);
   24029           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   24030           6 :     CHECK_EQ(arraysize(names), keys->Length());
   24031             :     // 0 -> 42
   24032          18 :     CHECK(v8_num(0)->SameValue(keys->Get(env.local(), 0).ToLocalChecked()));
   24033          12 :     CHECK(
   24034             :         values[0]->SameValue(obj->Get(env.local(), names[0]).ToLocalChecked()));
   24035             :     // "x" -> 24
   24036          18 :     CHECK(v8_str("x")->SameValue(keys->Get(env.local(), 1).ToLocalChecked()));
   24037          12 :     CHECK(
   24038             :         values[1]->SameValue(obj->Get(env.local(), names[1]).ToLocalChecked()));
   24039             :   }
   24040             :   {
   24041             :     // Verify that this also works for a couple thousand properties.
   24042             :     size_t const kLength = 10 * 1024;
   24043       61446 :     Local<v8::Name> names[kLength];
   24044       61440 :     Local<v8::Value> values[kLength];
   24045       61440 :     for (size_t i = 0; i < arraysize(names); ++i) {
   24046       61440 :       std::ostringstream ost;
   24047       61440 :       ost << "a" << i;
   24048      122880 :       names[i] = v8_str(ost.str().c_str());
   24049       61440 :       values[i] = v8_num(static_cast<double>(i));
   24050       61440 :     }
   24051             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   24052           6 :                                             values, arraysize(names));
   24053             :     Verify(isolate, obj);
   24054           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   24055           6 :     CHECK_EQ(arraysize(names), keys->Length());
   24056       61440 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   24057      184320 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   24058      184320 :       CHECK(values[i]->SameValue(
   24059             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   24060             :     }
   24061           6 :   }
   24062           6 : }
   24063             : 
   24064       28342 : TEST(EscapableHandleScope) {
   24065           5 :   HandleScope outer_scope(CcTest::isolate());
   24066          10 :   LocalContext context;
   24067             :   const int runs = 10;
   24068          55 :   Local<String> values[runs];
   24069          50 :   for (int i = 0; i < runs; i++) {
   24070          50 :     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   24071             :     Local<String> value;
   24072          50 :     if (i != 0) value = v8_str("escape value");
   24073          50 :     if (i < runs / 2) {
   24074          25 :       values[i] = inner_scope.Escape(value);
   24075             :     } else {
   24076             :       values[i] = inner_scope.EscapeMaybe(v8::MaybeLocal<String>(value))
   24077          25 :                       .ToLocalChecked();
   24078             :     }
   24079             :   }
   24080          50 :   for (int i = 0; i < runs; i++) {
   24081             :     Local<String> expected;
   24082          50 :     if (i != 0) {
   24083         135 :       CHECK(v8_str("escape value")
   24084             :                 ->Equals(context.local(), values[i])
   24085             :                 .FromJust());
   24086             :     } else {
   24087          10 :       CHECK(values[i].IsEmpty());
   24088             :     }
   24089           5 :   }
   24090           5 : }
   24091             : 
   24092             : 
   24093          20 : static void SetterWhichExpectsThisAndHolderToDiffer(
   24094             :     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   24095          20 :   CHECK(info.Holder() != info.This());
   24096          20 : }
   24097             : 
   24098             : 
   24099       28342 : TEST(Regress239669) {
   24100           5 :   LocalContext context;
   24101           5 :   v8::Isolate* isolate = context->GetIsolate();
   24102          10 :   v8::HandleScope scope(isolate);
   24103           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   24104             :   templ->SetAccessor(v8_str("x"), nullptr,
   24105           5 :                      SetterWhichExpectsThisAndHolderToDiffer);
   24106          30 :   CHECK(context->Global()
   24107             :             ->Set(context.local(), v8_str("P"),
   24108             :                   templ->NewInstance(context.local()).ToLocalChecked())
   24109             :             .FromJust());
   24110             :   CompileRun(
   24111             :       "function C1() {"
   24112             :       "  this.x = 23;"
   24113             :       "};"
   24114             :       "C1.prototype = P;"
   24115             :       "for (var i = 0; i < 4; i++ ) {"
   24116             :       "  new C1();"
   24117           5 :       "}");
   24118           5 : }
   24119             : 
   24120             : 
   24121             : class ApiCallOptimizationChecker {
   24122             :  private:
   24123             :   static Local<Object> data;
   24124             :   static Local<Object> receiver;
   24125             :   static Local<Object> holder;
   24126             :   static Local<Object> callee;
   24127             :   static int count;
   24128             : 
   24129         270 :   static void OptimizationCallback(
   24130        1350 :       const v8::FunctionCallbackInfo<v8::Value>& info) {
   24131         270 :     CHECK(data == info.Data());
   24132         270 :     CHECK(receiver == info.This());
   24133         270 :     if (info.Length() == 1) {
   24134         270 :       CHECK(v8_num(1)
   24135             :                 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
   24136             :                 .FromJust());
   24137             :     }
   24138         270 :     CHECK(holder == info.Holder());
   24139         270 :     count++;
   24140         270 :     info.GetReturnValue().Set(v8_str("returned"));
   24141         270 :   }
   24142             : 
   24143             :  public:
   24144             :   enum SignatureType {
   24145             :     kNoSignature,
   24146             :     kSignatureOnReceiver,
   24147             :     kSignatureOnPrototype
   24148             :   };
   24149             : 
   24150           5 :   void RunAll() {
   24151             :     SignatureType signature_types[] =
   24152           5 :       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   24153          20 :     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   24154          15 :       SignatureType signature_type = signature_types[i];
   24155          45 :       for (int j = 0; j < 2; j++) {
   24156          30 :         bool global = j == 0;
   24157             :         int key = signature_type +
   24158          30 :             arraysize(signature_types) * (global ? 1 : 0);
   24159          30 :         Run(signature_type, global, key);
   24160             :       }
   24161             :     }
   24162           5 :   }
   24163             : 
   24164          30 :   void Run(SignatureType signature_type, bool global, int key) {
   24165          30 :     v8::Isolate* isolate = CcTest::isolate();
   24166          30 :     v8::HandleScope scope(isolate);
   24167             :     // Build a template for signature checks.
   24168             :     Local<v8::ObjectTemplate> signature_template;
   24169             :     Local<v8::Signature> signature;
   24170             :     {
   24171             :       Local<v8::FunctionTemplate> parent_template =
   24172          30 :         FunctionTemplate::New(isolate);
   24173          30 :       parent_template->SetHiddenPrototype(true);
   24174             :       Local<v8::FunctionTemplate> function_template
   24175          30 :           = FunctionTemplate::New(isolate);
   24176          30 :       function_template->Inherit(parent_template);
   24177          30 :       switch (signature_type) {
   24178             :         case kNoSignature:
   24179             :           break;
   24180             :         case kSignatureOnReceiver:
   24181          10 :           signature = v8::Signature::New(isolate, function_template);
   24182          10 :           break;
   24183             :         case kSignatureOnPrototype:
   24184          10 :           signature = v8::Signature::New(isolate, parent_template);
   24185          10 :           break;
   24186             :       }
   24187          30 :       signature_template = function_template->InstanceTemplate();
   24188             :     }
   24189             :     // Global object must pass checks.
   24190             :     Local<v8::Context> context =
   24191          30 :         v8::Context::New(isolate, nullptr, signature_template);
   24192             :     v8::Context::Scope context_scope(context);
   24193             :     // Install regular object that can pass signature checks.
   24194             :     Local<Object> function_receiver =
   24195          30 :         signature_template->NewInstance(context).ToLocalChecked();
   24196         120 :     CHECK(context->Global()
   24197             :               ->Set(context, v8_str("function_receiver"), function_receiver)
   24198             :               .FromJust());
   24199             :     // Get the holder objects.
   24200             :     Local<Object> inner_global =
   24201          60 :         Local<Object>::Cast(context->Global()->GetPrototype());
   24202             :     // Install functions on hidden prototype object if there is one.
   24203          30 :     data = Object::New(isolate);
   24204             :     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   24205          30 :         isolate, OptimizationCallback, data, signature);
   24206             :     Local<Function> function =
   24207          30 :         function_template->GetFunction(context).ToLocalChecked();
   24208             :     Local<Object> global_holder = inner_global;
   24209             :     Local<Object> function_holder = function_receiver;
   24210          30 :     if (signature_type == kSignatureOnPrototype) {
   24211          10 :       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   24212          10 :       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   24213             :     }
   24214          90 :     global_holder->Set(context, v8_str("g_f"), function).FromJust();
   24215          60 :     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   24216          90 :     function_holder->Set(context, v8_str("f"), function).FromJust();
   24217          60 :     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   24218             :     // Initialize expected values.
   24219          30 :     callee = function;
   24220          30 :     count = 0;
   24221          30 :     if (global) {
   24222          15 :       receiver = context->Global();
   24223          15 :       holder = inner_global;
   24224             :     } else {
   24225          15 :       holder = function_receiver;
   24226             :       // If not using a signature, add something else to the prototype chain
   24227             :       // to test the case that holder != receiver
   24228          15 :       if (signature_type == kNoSignature) {
   24229             :         receiver = Local<Object>::Cast(CompileRun(
   24230             :             "var receiver_subclass = {};\n"
   24231             :             "receiver_subclass.__proto__ = function_receiver;\n"
   24232           5 :             "receiver_subclass"));
   24233             :       } else {
   24234             :         receiver = Local<Object>::Cast(CompileRun(
   24235             :           "var receiver_subclass = function_receiver;\n"
   24236          10 :           "receiver_subclass"));
   24237             :       }
   24238             :     }
   24239             :     // With no signature, the holder is not set.
   24240          30 :     if (signature_type == kNoSignature) holder = receiver;
   24241             :     // build wrap_function
   24242             :     i::ScopedVector<char> wrap_function(200);
   24243          30 :     if (global) {
   24244             :       i::SNPrintF(
   24245             :           wrap_function,
   24246             :           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   24247             :           "function wrap_get_%d() { return this.g_acc; }\n"
   24248             :           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   24249          15 :           key, key, key);
   24250             :     } else {
   24251             :       i::SNPrintF(
   24252             :           wrap_function,
   24253             :           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   24254             :           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   24255             :           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   24256          15 :           key, key, key);
   24257             :     }
   24258             :     // build source string
   24259             :     i::ScopedVector<char> source(1000);
   24260             :     i::SNPrintF(
   24261             :         source,
   24262             :         "%s\n"  // wrap functions
   24263             :         "function wrap_f() { return wrap_f_%d(); }\n"
   24264             :         "function wrap_get() { return wrap_get_%d(); }\n"
   24265             :         "function wrap_set() { return wrap_set_%d(); }\n"
   24266             :         "check = function(returned) {\n"
   24267             :         "  if (returned !== 'returned') { throw returned; }\n"
   24268             :         "}\n"
   24269             :         "\n"
   24270             :         "check(wrap_f());\n"
   24271             :         "check(wrap_f());\n"
   24272             :         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   24273             :         "check(wrap_f());\n"
   24274             :         "\n"
   24275             :         "check(wrap_get());\n"
   24276             :         "check(wrap_get());\n"
   24277             :         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   24278             :         "check(wrap_get());\n"
   24279             :         "\n"
   24280             :         "check = function(returned) {\n"
   24281             :         "  if (returned !== 1) { throw returned; }\n"
   24282             :         "}\n"
   24283             :         "check(wrap_set());\n"
   24284             :         "check(wrap_set());\n"
   24285             :         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   24286             :         "check(wrap_set());\n",
   24287          30 :         wrap_function.start(), key, key, key, key, key, key);
   24288          60 :     v8::TryCatch try_catch(isolate);
   24289             :     CompileRun(source.start());
   24290          30 :     CHECK(!try_catch.HasCaught());
   24291          60 :     CHECK_EQ(9, count);
   24292          30 :   }
   24293             : };
   24294             : 
   24295             : 
   24296             : Local<Object> ApiCallOptimizationChecker::data;
   24297             : Local<Object> ApiCallOptimizationChecker::receiver;
   24298             : Local<Object> ApiCallOptimizationChecker::holder;
   24299             : Local<Object> ApiCallOptimizationChecker::callee;
   24300             : int ApiCallOptimizationChecker::count = 0;
   24301             : 
   24302             : 
   24303       28342 : TEST(FunctionCallOptimization) {
   24304           5 :   i::FLAG_allow_natives_syntax = true;
   24305             :   ApiCallOptimizationChecker checker;
   24306           5 :   checker.RunAll();
   24307           5 : }
   24308             : 
   24309             : 
   24310       28342 : TEST(FunctionCallOptimizationMultipleArgs) {
   24311           5 :   i::FLAG_allow_natives_syntax = true;
   24312           5 :   LocalContext context;
   24313           5 :   v8::Isolate* isolate = context->GetIsolate();
   24314          10 :   v8::HandleScope scope(isolate);
   24315           5 :   Local<Object> global = context->Global();
   24316             :   Local<v8::Function> function =
   24317          10 :       Function::New(context.local(), Returns42).ToLocalChecked();
   24318          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   24319             :   CompileRun(
   24320             :       "function x_wrap() {\n"
   24321             :       "  for (var i = 0; i < 5; i++) {\n"
   24322             :       "    x(1,2,3);\n"
   24323             :       "  }\n"
   24324             :       "}\n"
   24325             :       "x_wrap();\n"
   24326             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   24327           5 :       "x_wrap();\n");
   24328           5 : }
   24329             : 
   24330             : 
   24331          50 : static void ReturnsSymbolCallback(
   24332         100 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   24333         100 :   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
   24334          50 : }
   24335             : 
   24336             : 
   24337       28342 : TEST(ApiCallbackCanReturnSymbols) {
   24338           5 :   i::FLAG_allow_natives_syntax = true;
   24339           5 :   LocalContext context;
   24340           5 :   v8::Isolate* isolate = context->GetIsolate();
   24341          10 :   v8::HandleScope scope(isolate);
   24342           5 :   Local<Object> global = context->Global();
   24343             :   Local<v8::Function> function =
   24344          10 :       Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
   24345          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   24346             :   CompileRun(
   24347             :       "function x_wrap() {\n"
   24348             :       "  for (var i = 0; i < 5; i++) {\n"
   24349             :       "    x();\n"
   24350             :       "  }\n"
   24351             :       "}\n"
   24352             :       "x_wrap();\n"
   24353             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   24354           5 :       "x_wrap();\n");
   24355           5 : }
   24356             : 
   24357             : 
   24358       28342 : TEST(EmptyApiCallback) {
   24359           5 :   LocalContext context;
   24360           5 :   auto isolate = context->GetIsolate();
   24361          10 :   v8::HandleScope scope(isolate);
   24362           5 :   auto global = context->Global();
   24363           5 :   auto function = FunctionTemplate::New(isolate)
   24364          15 :                       ->GetFunction(context.local())
   24365           5 :                       .ToLocalChecked();
   24366          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   24367             : 
   24368             :   auto result = CompileRun("x()");
   24369          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24370             : 
   24371             :   result = CompileRun("x(1,2,3)");
   24372          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24373             : 
   24374             :   result = CompileRun("x.call(undefined)");
   24375          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24376             : 
   24377             :   result = CompileRun("x.call(null)");
   24378          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   24379             : 
   24380             :   result = CompileRun("7 + x.call(3) + 11");
   24381           5 :   CHECK(result->IsInt32());
   24382          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   24383             : 
   24384             :   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
   24385           5 :   CHECK(result->IsInt32());
   24386          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   24387             : 
   24388             :   result = CompileRun("var y = []; x.call(y)");
   24389           5 :   CHECK(result->IsArray());
   24390             : 
   24391             :   result = CompileRun("x.call(y, 1, 2, 3, 4)");
   24392          10 :   CHECK(result->IsArray());
   24393           5 : }
   24394             : 
   24395             : 
   24396       28342 : TEST(SimpleSignatureCheck) {
   24397           5 :   LocalContext context;
   24398           5 :   auto isolate = context->GetIsolate();
   24399          10 :   v8::HandleScope scope(isolate);
   24400           5 :   auto global = context->Global();
   24401           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   24402           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   24403           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   24404             :   global->Set(context.local(), v8_str("sig_obj"),
   24405          25 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   24406          10 :       .FromJust();
   24407             :   global->Set(context.local(), v8_str("x"),
   24408          25 :               x->GetFunction(context.local()).ToLocalChecked())
   24409          10 :       .FromJust();
   24410             :   CompileRun("var s = new sig_obj();");
   24411             :   {
   24412           5 :     TryCatch try_catch(isolate);
   24413             :     CompileRun("x()");
   24414           5 :     CHECK(try_catch.HasCaught());
   24415             :   }
   24416             :   {
   24417           5 :     TryCatch try_catch(isolate);
   24418             :     CompileRun("x.call(1)");
   24419           5 :     CHECK(try_catch.HasCaught());
   24420             :   }
   24421             :   {
   24422           5 :     TryCatch try_catch(isolate);
   24423             :     auto result = CompileRun("s.x = x; s.x()");
   24424           5 :     CHECK(!try_catch.HasCaught());
   24425          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24426             :   }
   24427             :   {
   24428           5 :     TryCatch try_catch(isolate);
   24429             :     auto result = CompileRun("x.call(s)");
   24430           5 :     CHECK(!try_catch.HasCaught());
   24431          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24432           5 :   }
   24433           5 : }
   24434             : 
   24435             : 
   24436       28342 : TEST(ChainSignatureCheck) {
   24437           5 :   LocalContext context;
   24438           5 :   auto isolate = context->GetIsolate();
   24439          10 :   v8::HandleScope scope(isolate);
   24440           5 :   auto global = context->Global();
   24441           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   24442           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   24443          25 :   for (int i = 0; i < 4; ++i) {
   24444          20 :     auto temp = FunctionTemplate::New(isolate);
   24445          20 :     temp->Inherit(sig_obj);
   24446             :     sig_obj = temp;
   24447             :   }
   24448           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   24449             :   global->Set(context.local(), v8_str("sig_obj"),
   24450          20 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   24451          10 :       .FromJust();
   24452             :   global->Set(context.local(), v8_str("x"),
   24453          25 :               x->GetFunction(context.local()).ToLocalChecked())
   24454          10 :       .FromJust();
   24455             :   CompileRun("var s = new sig_obj();");
   24456             :   {
   24457           5 :     TryCatch try_catch(isolate);
   24458             :     CompileRun("x()");
   24459           5 :     CHECK(try_catch.HasCaught());
   24460             :   }
   24461             :   {
   24462           5 :     TryCatch try_catch(isolate);
   24463             :     CompileRun("x.call(1)");
   24464           5 :     CHECK(try_catch.HasCaught());
   24465             :   }
   24466             :   {
   24467           5 :     TryCatch try_catch(isolate);
   24468             :     auto result = CompileRun("s.x = x; s.x()");
   24469           5 :     CHECK(!try_catch.HasCaught());
   24470          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24471             :   }
   24472             :   {
   24473           5 :     TryCatch try_catch(isolate);
   24474             :     auto result = CompileRun("x.call(s)");
   24475           5 :     CHECK(!try_catch.HasCaught());
   24476          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24477           5 :   }
   24478           5 : }
   24479             : 
   24480             : 
   24481       28342 : TEST(PrototypeSignatureCheck) {
   24482           5 :   LocalContext context;
   24483           5 :   auto isolate = context->GetIsolate();
   24484          10 :   v8::HandleScope scope(isolate);
   24485           5 :   auto global = context->Global();
   24486           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   24487           5 :   sig_obj->SetHiddenPrototype(true);
   24488           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   24489           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   24490             :   global->Set(context.local(), v8_str("sig_obj"),
   24491          20 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   24492          10 :       .FromJust();
   24493             :   global->Set(context.local(), v8_str("x"),
   24494          25 :               x->GetFunction(context.local()).ToLocalChecked())
   24495          10 :       .FromJust();
   24496             :   CompileRun("s = {}; s.__proto__ = new sig_obj();");
   24497             :   {
   24498           5 :     TryCatch try_catch(isolate);
   24499             :     CompileRun("x()");
   24500           5 :     CHECK(try_catch.HasCaught());
   24501             :   }
   24502             :   {
   24503           5 :     TryCatch try_catch(isolate);
   24504             :     CompileRun("x.call(1)");
   24505           5 :     CHECK(try_catch.HasCaught());
   24506             :   }
   24507             :   {
   24508           5 :     TryCatch try_catch(isolate);
   24509             :     auto result = CompileRun("s.x = x; s.x()");
   24510           5 :     CHECK(!try_catch.HasCaught());
   24511          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24512             :   }
   24513             :   {
   24514           5 :     TryCatch try_catch(isolate);
   24515             :     auto result = CompileRun("x.call(s)");
   24516           5 :     CHECK(!try_catch.HasCaught());
   24517          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   24518           5 :   }
   24519           5 : }
   24520             : 
   24521             : 
   24522             : static const char* last_event_message;
   24523             : static int last_event_status;
   24524          10 : void StoringEventLoggerCallback(const char* message, int status) {
   24525          10 :     last_event_message = message;
   24526          10 :     last_event_status = status;
   24527          10 : }
   24528             : 
   24529             : 
   24530       28342 : TEST(EventLogging) {
   24531           5 :   v8::Isolate* isolate = CcTest::isolate();
   24532           5 :   isolate->SetEventLogger(StoringEventLoggerCallback);
   24533             :   v8::internal::HistogramTimer histogramTimer(
   24534             :       "V8.Test", 0, 10000, v8::internal::HistogramTimerResolution::MILLISECOND,
   24535             :       50, reinterpret_cast<v8::internal::Isolate*>(isolate)->counters());
   24536             :   histogramTimer.Start();
   24537           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   24538           5 :   CHECK_EQ(0, last_event_status);
   24539             :   histogramTimer.Stop();
   24540           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   24541           5 :   CHECK_EQ(1, last_event_status);
   24542           5 : }
   24543             : 
   24544       28342 : TEST(PropertyDescriptor) {
   24545           5 :   LocalContext context;
   24546           5 :   v8::Isolate* isolate = context->GetIsolate();
   24547          10 :   v8::HandleScope scope(isolate);
   24548             : 
   24549             :   {  // empty descriptor
   24550           5 :     v8::PropertyDescriptor desc;
   24551           5 :     CHECK(!desc.has_value());
   24552           5 :     CHECK(!desc.has_set());
   24553           5 :     CHECK(!desc.has_get());
   24554           5 :     CHECK(!desc.has_enumerable());
   24555           5 :     CHECK(!desc.has_configurable());
   24556           5 :     CHECK(!desc.has_writable());
   24557             :   }
   24558             :   {
   24559             :     // data descriptor
   24560           5 :     v8::PropertyDescriptor desc(v8_num(42));
   24561           5 :     desc.set_enumerable(false);
   24562          10 :     CHECK(desc.value() == v8_num(42));
   24563           5 :     CHECK(desc.has_value());
   24564           5 :     CHECK(!desc.has_set());
   24565           5 :     CHECK(!desc.has_get());
   24566           5 :     CHECK(desc.has_enumerable());
   24567           5 :     CHECK(!desc.enumerable());
   24568           5 :     CHECK(!desc.has_configurable());
   24569           5 :     CHECK(!desc.has_writable());
   24570             :   }
   24571             :   {
   24572             :     // data descriptor
   24573           5 :     v8::PropertyDescriptor desc(v8_num(42));
   24574           5 :     desc.set_configurable(true);
   24575          10 :     CHECK(desc.value() == v8_num(42));
   24576           5 :     CHECK(desc.has_value());
   24577           5 :     CHECK(!desc.has_set());
   24578           5 :     CHECK(!desc.has_get());
   24579           5 :     CHECK(desc.has_configurable());
   24580           5 :     CHECK(desc.configurable());
   24581           5 :     CHECK(!desc.has_enumerable());
   24582           5 :     CHECK(!desc.has_writable());
   24583             :   }
   24584             :   {
   24585             :     // data descriptor
   24586           5 :     v8::PropertyDescriptor desc(v8_num(42));
   24587           5 :     desc.set_configurable(false);
   24588          10 :     CHECK(desc.value() == v8_num(42));
   24589           5 :     CHECK(desc.has_value());
   24590           5 :     CHECK(!desc.has_set());
   24591           5 :     CHECK(!desc.has_get());
   24592           5 :     CHECK(desc.has_configurable());
   24593           5 :     CHECK(!desc.configurable());
   24594           5 :     CHECK(!desc.has_enumerable());
   24595           5 :     CHECK(!desc.has_writable());
   24596             :   }
   24597             :   {
   24598             :     // data descriptor
   24599           5 :     v8::PropertyDescriptor desc(v8_num(42), false);
   24600          10 :     CHECK(desc.value() == v8_num(42));
   24601           5 :     CHECK(desc.has_value());
   24602           5 :     CHECK(!desc.has_set());
   24603           5 :     CHECK(!desc.has_get());
   24604           5 :     CHECK(!desc.has_enumerable());
   24605           5 :     CHECK(!desc.has_configurable());
   24606           5 :     CHECK(desc.has_writable());
   24607           5 :     CHECK(!desc.writable());
   24608             :   }
   24609             :   {
   24610             :     // data descriptor
   24611           5 :     v8::PropertyDescriptor desc(v8::Local<v8::Value>(), true);
   24612           5 :     CHECK(!desc.has_value());
   24613           5 :     CHECK(!desc.has_set());
   24614           5 :     CHECK(!desc.has_get());
   24615           5 :     CHECK(!desc.has_enumerable());
   24616           5 :     CHECK(!desc.has_configurable());
   24617           5 :     CHECK(desc.has_writable());
   24618           5 :     CHECK(desc.writable());
   24619             :   }
   24620             :   {
   24621             :     // accessor descriptor
   24622             :     CompileRun("var set = function() {return 43;};");
   24623             : 
   24624             :     v8::Local<v8::Function> set =
   24625             :         v8::Local<v8::Function>::Cast(context->Global()
   24626          20 :                                           ->Get(context.local(), v8_str("set"))
   24627           5 :                                           .ToLocalChecked());
   24628           5 :     v8::PropertyDescriptor desc(v8::Undefined(isolate), set);
   24629           5 :     desc.set_configurable(false);
   24630           5 :     CHECK(!desc.has_value());
   24631           5 :     CHECK(desc.has_get());
   24632          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   24633           5 :     CHECK(desc.has_set());
   24634          10 :     CHECK(desc.set() == set);
   24635           5 :     CHECK(!desc.has_enumerable());
   24636           5 :     CHECK(desc.has_configurable());
   24637           5 :     CHECK(!desc.configurable());
   24638           5 :     CHECK(!desc.has_writable());
   24639             :   }
   24640             :   {
   24641             :     // accessor descriptor with Proxy
   24642             :     CompileRun(
   24643             :         "var set = new Proxy(function() {}, {});"
   24644             :         "var get = undefined;");
   24645             : 
   24646             :     v8::Local<v8::Value> get =
   24647             :         v8::Local<v8::Value>::Cast(context->Global()
   24648          20 :                                        ->Get(context.local(), v8_str("get"))
   24649          10 :                                        .ToLocalChecked());
   24650             :     v8::Local<v8::Function> set =
   24651             :         v8::Local<v8::Function>::Cast(context->Global()
   24652          20 :                                           ->Get(context.local(), v8_str("set"))
   24653           5 :                                           .ToLocalChecked());
   24654           5 :     v8::PropertyDescriptor desc(get, set);
   24655           5 :     desc.set_configurable(false);
   24656           5 :     CHECK(!desc.has_value());
   24657          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   24658           5 :     CHECK(desc.has_get());
   24659          10 :     CHECK(desc.set() == set);
   24660           5 :     CHECK(desc.has_set());
   24661           5 :     CHECK(!desc.has_enumerable());
   24662           5 :     CHECK(desc.has_configurable());
   24663           5 :     CHECK(!desc.configurable());
   24664           5 :     CHECK(!desc.has_writable());
   24665             :   }
   24666             :   {
   24667             :     // accessor descriptor with empty function handle
   24668             :     v8::Local<v8::Function> get = v8::Local<v8::Function>();
   24669           5 :     v8::PropertyDescriptor desc(get, get);
   24670           5 :     CHECK(!desc.has_value());
   24671           5 :     CHECK(!desc.has_get());
   24672           5 :     CHECK(!desc.has_set());
   24673           5 :     CHECK(!desc.has_enumerable());
   24674           5 :     CHECK(!desc.has_configurable());
   24675           5 :     CHECK(!desc.has_writable());
   24676           5 :   }
   24677           5 : }
   24678             : 
   24679       28342 : TEST(Promises) {
   24680           5 :   LocalContext context;
   24681           5 :   v8::Isolate* isolate = context->GetIsolate();
   24682          10 :   v8::HandleScope scope(isolate);
   24683             : 
   24684             :   // Creation.
   24685             :   Local<v8::Promise::Resolver> pr =
   24686           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24687             :   Local<v8::Promise::Resolver> rr =
   24688           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24689           5 :   Local<v8::Promise> p = pr->GetPromise();
   24690           5 :   Local<v8::Promise> r = rr->GetPromise();
   24691             : 
   24692             :   // IsPromise predicate.
   24693           5 :   CHECK(p->IsPromise());
   24694           5 :   CHECK(r->IsPromise());
   24695           5 :   Local<Value> o = v8::Object::New(isolate);
   24696           5 :   CHECK(!o->IsPromise());
   24697             : 
   24698             :   // Resolution and rejection.
   24699          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24700           5 :   CHECK(p->IsPromise());
   24701          15 :   rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
   24702          10 :   CHECK(r->IsPromise());
   24703           5 : }
   24704             : 
   24705             : // Promise.Then(on_fulfilled)
   24706       28342 : TEST(PromiseThen) {
   24707           5 :   LocalContext context;
   24708           5 :   v8::Isolate* isolate = context->GetIsolate();
   24709           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   24710          10 :   v8::HandleScope scope(isolate);
   24711           5 :   Local<Object> global = context->Global();
   24712             : 
   24713             :   // Creation.
   24714             :   Local<v8::Promise::Resolver> pr =
   24715           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24716             :   Local<v8::Promise::Resolver> qr =
   24717           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24718           5 :   Local<v8::Promise> p = pr->GetPromise();
   24719           5 :   Local<v8::Promise> q = qr->GetPromise();
   24720             : 
   24721           5 :   CHECK(p->IsPromise());
   24722           5 :   CHECK(q->IsPromise());
   24723             : 
   24724          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24725          10 :   qr->Resolve(context.local(), p).FromJust();
   24726             : 
   24727             :   // Chaining non-pending promises.
   24728             :   CompileRun(
   24729             :       "var x1 = 0;\n"
   24730             :       "var x2 = 0;\n"
   24731             :       "function f1(x) { x1 = x; return x+1 };\n"
   24732             :       "function f2(x) { x2 = x; return x+1 };\n");
   24733             :   Local<Function> f1 = Local<Function>::Cast(
   24734          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   24735             :   Local<Function> f2 = Local<Function>::Cast(
   24736          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   24737             : 
   24738             :   // Then
   24739             :   CompileRun("x1 = x2 = 0;");
   24740           5 :   q->Then(context.local(), f1).ToLocalChecked();
   24741          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24742             :                   .ToLocalChecked()
   24743             :                   ->Int32Value(context.local())
   24744             :                   .FromJust());
   24745           5 :   isolate->RunMicrotasks();
   24746          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24747             :                   .ToLocalChecked()
   24748             :                   ->Int32Value(context.local())
   24749             :                   .FromJust());
   24750             : 
   24751             :   // Then
   24752             :   CompileRun("x1 = x2 = 0;");
   24753           5 :   pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24754           5 :   qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24755             : 
   24756          10 :   qr->Resolve(context.local(), pr).FromJust();
   24757             :   qr->GetPromise()
   24758          10 :       ->Then(context.local(), f1)
   24759           5 :       .ToLocalChecked()
   24760           5 :       ->Then(context.local(), f2)
   24761           5 :       .ToLocalChecked();
   24762             : 
   24763          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24764             :                   .ToLocalChecked()
   24765             :                   ->Int32Value(context.local())
   24766             :                   .FromJust());
   24767          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24768             :                   .ToLocalChecked()
   24769             :                   ->Int32Value(context.local())
   24770             :                   .FromJust());
   24771           5 :   isolate->RunMicrotasks();
   24772          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24773             :                   .ToLocalChecked()
   24774             :                   ->Int32Value(context.local())
   24775             :                   .FromJust());
   24776          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24777             :                   .ToLocalChecked()
   24778             :                   ->Int32Value(context.local())
   24779             :                   .FromJust());
   24780             : 
   24781          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
   24782             : 
   24783          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24784             :                   .ToLocalChecked()
   24785             :                   ->Int32Value(context.local())
   24786             :                   .FromJust());
   24787          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24788             :                   .ToLocalChecked()
   24789             :                   ->Int32Value(context.local())
   24790             :                   .FromJust());
   24791           5 :   isolate->RunMicrotasks();
   24792          20 :   CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
   24793             :                   .ToLocalChecked()
   24794             :                   ->Int32Value(context.local())
   24795             :                   .FromJust());
   24796          20 :   CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
   24797             :                   .ToLocalChecked()
   24798             :                   ->Int32Value(context.local())
   24799           5 :                   .FromJust());
   24800           5 : }
   24801             : 
   24802             : // Promise.Then(on_fulfilled, on_rejected)
   24803       28342 : TEST(PromiseThen2) {
   24804           5 :   LocalContext context;
   24805           5 :   v8::Isolate* isolate = context->GetIsolate();
   24806           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   24807          10 :   v8::HandleScope scope(isolate);
   24808           5 :   Local<Object> global = context->Global();
   24809             : 
   24810             :   // Creation.
   24811             :   Local<v8::Promise::Resolver> pr =
   24812           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24813           5 :   Local<v8::Promise> p = pr->GetPromise();
   24814             : 
   24815           5 :   CHECK(p->IsPromise());
   24816             : 
   24817          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24818             : 
   24819             :   // Chaining non-pending promises.
   24820             :   CompileRun(
   24821             :       "var x1 = 0;\n"
   24822             :       "var x2 = 0;\n"
   24823             :       "function f1(x) { x1 = x; return x+1 };\n"
   24824             :       "function f2(x) { x2 = x; return x+1 };\n"
   24825             :       "function f3(x) { throw x + 100 };\n");
   24826             :   Local<Function> f1 = Local<Function>::Cast(
   24827          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   24828             :   Local<Function> f2 = Local<Function>::Cast(
   24829          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   24830             :   Local<Function> f3 = Local<Function>::Cast(
   24831          15 :       global->Get(context.local(), v8_str("f3")).ToLocalChecked());
   24832             : 
   24833             :   // Then
   24834             :   CompileRun("x1 = x2 = 0;");
   24835           5 :   Local<v8::Promise> a = p->Then(context.local(), f1, f2).ToLocalChecked();
   24836          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24837             :                   .ToLocalChecked()
   24838             :                   ->Int32Value(context.local())
   24839             :                   .FromJust());
   24840           5 :   isolate->RunMicrotasks();
   24841          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24842             :                   .ToLocalChecked()
   24843             :                   ->Int32Value(context.local())
   24844             :                   .FromJust());
   24845          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24846             :                   .ToLocalChecked()
   24847             :                   ->Int32Value(context.local())
   24848             :                   .FromJust());
   24849             : 
   24850           5 :   Local<v8::Promise> b = a->Then(context.local(), f3, f2).ToLocalChecked();
   24851           5 :   isolate->RunMicrotasks();
   24852          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24853             :                   .ToLocalChecked()
   24854             :                   ->Int32Value(context.local())
   24855             :                   .FromJust());
   24856          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24857             :                   .ToLocalChecked()
   24858             :                   ->Int32Value(context.local())
   24859             :                   .FromJust());
   24860             : 
   24861           5 :   Local<v8::Promise> c = b->Then(context.local(), f1, f2).ToLocalChecked();
   24862           5 :   isolate->RunMicrotasks();
   24863          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24864             :                   .ToLocalChecked()
   24865             :                   ->Int32Value(context.local())
   24866             :                   .FromJust());
   24867          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24868             :                     .ToLocalChecked()
   24869             :                     ->Int32Value(context.local())
   24870             :                     .FromJust());
   24871             : 
   24872           5 :   v8::Local<v8::Promise> d = c->Then(context.local(), f1, f2).ToLocalChecked();
   24873           5 :   isolate->RunMicrotasks();
   24874          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24875             :                     .ToLocalChecked()
   24876             :                     ->Int32Value(context.local())
   24877             :                     .FromJust());
   24878          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24879             :                     .ToLocalChecked()
   24880             :                     ->Int32Value(context.local())
   24881             :                     .FromJust());
   24882             : 
   24883           5 :   v8::Local<v8::Promise> e = d->Then(context.local(), f3, f2).ToLocalChecked();
   24884           5 :   isolate->RunMicrotasks();
   24885          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24886             :                     .ToLocalChecked()
   24887             :                     ->Int32Value(context.local())
   24888             :                     .FromJust());
   24889          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24890             :                     .ToLocalChecked()
   24891             :                     ->Int32Value(context.local())
   24892             :                     .FromJust());
   24893             : 
   24894           5 :   v8::Local<v8::Promise> f = e->Then(context.local(), f1, f3).ToLocalChecked();
   24895           5 :   isolate->RunMicrotasks();
   24896          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24897             :                     .ToLocalChecked()
   24898             :                     ->Int32Value(context.local())
   24899             :                     .FromJust());
   24900          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24901             :                     .ToLocalChecked()
   24902             :                     ->Int32Value(context.local())
   24903             :                     .FromJust());
   24904             : 
   24905           5 :   f->Then(context.local(), f1, f2).ToLocalChecked();
   24906           5 :   isolate->RunMicrotasks();
   24907          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24908             :                     .ToLocalChecked()
   24909             :                     ->Int32Value(context.local())
   24910             :                     .FromJust());
   24911          20 :   CHECK_EQ(304, global->Get(context.local(), v8_str("x2"))
   24912             :                     .ToLocalChecked()
   24913             :                     ->Int32Value(context.local())
   24914           5 :                     .FromJust());
   24915           5 : }
   24916             : 
   24917       28342 : TEST(PromiseStateAndValue) {
   24918           5 :   LocalContext context;
   24919           5 :   v8::Isolate* isolate = context->GetIsolate();
   24920          10 :   v8::HandleScope scope(isolate);
   24921             :   v8::Local<v8::Value> result = CompileRun(
   24922             :       "var resolver;"
   24923             :       "new Promise((res, rej) => { resolver = res; })");
   24924             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(result);
   24925           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24926             : 
   24927             :   CompileRun("resolver('fulfilled')");
   24928           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24929          10 :   CHECK(v8_str("fulfilled")->SameValue(promise->Result()));
   24930             : 
   24931             :   result = CompileRun("Promise.reject('rejected')");
   24932             :   promise = v8::Local<v8::Promise>::Cast(result);
   24933           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24934          15 :   CHECK(v8_str("rejected")->SameValue(promise->Result()));
   24935           5 : }
   24936             : 
   24937       28342 : TEST(ResolvedPromiseReFulfill) {
   24938           5 :   LocalContext context;
   24939           5 :   v8::Isolate* isolate = context->GetIsolate();
   24940          10 :   v8::HandleScope scope(isolate);
   24941             :   v8::Local<v8::String> value1 =
   24942             :       v8::String::NewFromUtf8(isolate, "foo", v8::NewStringType::kNormal)
   24943           5 :           .ToLocalChecked();
   24944             :   v8::Local<v8::String> value2 =
   24945             :       v8::String::NewFromUtf8(isolate, "bar", v8::NewStringType::kNormal)
   24946           5 :           .ToLocalChecked();
   24947             : 
   24948             :   v8::Local<v8::Promise::Resolver> resolver =
   24949           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24950           5 :   v8::Local<v8::Promise> promise = resolver->GetPromise();
   24951           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24952             : 
   24953          10 :   resolver->Resolve(context.local(), value1).ToChecked();
   24954           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24955          10 :   CHECK_EQ(promise->Result(), value1);
   24956             : 
   24957             :   // This should be a no-op.
   24958          10 :   resolver->Resolve(context.local(), value2).ToChecked();
   24959           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24960          10 :   CHECK_EQ(promise->Result(), value1);
   24961             : 
   24962             :   // This should be a no-op.
   24963          10 :   resolver->Reject(context.local(), value2).ToChecked();
   24964           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24965          15 :   CHECK_EQ(promise->Result(), value1);
   24966           5 : }
   24967             : 
   24968       28342 : TEST(RejectedPromiseReFulfill) {
   24969           5 :   LocalContext context;
   24970           5 :   v8::Isolate* isolate = context->GetIsolate();
   24971          10 :   v8::HandleScope scope(isolate);
   24972             :   v8::Local<v8::String> value1 =
   24973             :       v8::String::NewFromUtf8(isolate, "foo", v8::NewStringType::kNormal)
   24974           5 :           .ToLocalChecked();
   24975             :   v8::Local<v8::String> value2 =
   24976             :       v8::String::NewFromUtf8(isolate, "bar", v8::NewStringType::kNormal)
   24977           5 :           .ToLocalChecked();
   24978             : 
   24979             :   v8::Local<v8::Promise::Resolver> resolver =
   24980           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24981           5 :   v8::Local<v8::Promise> promise = resolver->GetPromise();
   24982           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24983             : 
   24984          10 :   resolver->Reject(context.local(), value1).ToChecked();
   24985           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24986          10 :   CHECK_EQ(promise->Result(), value1);
   24987             : 
   24988             :   // This should be a no-op.
   24989          10 :   resolver->Reject(context.local(), value2).ToChecked();
   24990           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24991          10 :   CHECK_EQ(promise->Result(), value1);
   24992             : 
   24993             :   // This should be a no-op.
   24994          10 :   resolver->Resolve(context.local(), value2).ToChecked();
   24995           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24996          15 :   CHECK_EQ(promise->Result(), value1);
   24997           5 : }
   24998             : 
   24999       28337 : TEST(DisallowJavascriptExecutionScope) {
   25000           0 :   LocalContext context;
   25001           0 :   v8::Isolate* isolate = context->GetIsolate();
   25002           0 :   v8::HandleScope scope(isolate);
   25003             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   25004           0 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   25005           0 :   CompileRun("2+2");
   25006           0 : }
   25007             : 
   25008       28342 : TEST(AllowJavascriptExecutionScope) {
   25009           5 :   LocalContext context;
   25010           5 :   v8::Isolate* isolate = context->GetIsolate();
   25011          10 :   v8::HandleScope scope(isolate);
   25012             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   25013          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   25014             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   25015          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   25016           5 :   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   25017           5 :     CompileRun("1+1");
   25018           5 :   }
   25019           5 : }
   25020             : 
   25021       28342 : TEST(ThrowOnJavascriptExecution) {
   25022           5 :   LocalContext context;
   25023           5 :   v8::Isolate* isolate = context->GetIsolate();
   25024          10 :   v8::HandleScope scope(isolate);
   25025          10 :   v8::TryCatch try_catch(isolate);
   25026             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   25027          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   25028             :   CompileRun("1+1");
   25029          10 :   CHECK(try_catch.HasCaught());
   25030           5 : }
   25031             : 
   25032             : namespace {
   25033             : 
   25034             : class MockPlatform : public TestPlatform {
   25035             :  public:
   25036          10 :   MockPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {
   25037             :     // Now that it's completely constructed, make this the current platform.
   25038           5 :     i::V8::SetPlatformForTesting(this);
   25039           5 :   }
   25040          10 :   ~MockPlatform() override { i::V8::SetPlatformForTesting(old_platform_); }
   25041             : 
   25042             :   bool dump_without_crashing_called() const {
   25043             :     return dump_without_crashing_called_;
   25044             :   }
   25045             : 
   25046           5 :   void DumpWithoutCrashing() override { dump_without_crashing_called_ = true; }
   25047             : 
   25048             :  private:
   25049             :   v8::Platform* old_platform_;
   25050             :   bool dump_without_crashing_called_ = false;
   25051             : };
   25052             : 
   25053             : }  // namespace
   25054             : 
   25055       28342 : TEST(DumpOnJavascriptExecution) {
   25056           5 :   MockPlatform platform;
   25057             : 
   25058          10 :   LocalContext context;
   25059           5 :   v8::Isolate* isolate = context->GetIsolate();
   25060          10 :   v8::HandleScope scope(isolate);
   25061             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   25062          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::DUMP_ON_FAILURE);
   25063           5 :   CHECK(!platform.dump_without_crashing_called());
   25064             :   CompileRun("1+1");
   25065          10 :   CHECK(platform.dump_without_crashing_called());
   25066           5 : }
   25067             : 
   25068       28342 : TEST(Regress354123) {
   25069           5 :   LocalContext current;
   25070           5 :   v8::Isolate* isolate = current->GetIsolate();
   25071          10 :   v8::HandleScope scope(isolate);
   25072             : 
   25073           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   25074           5 :   templ->SetAccessCheckCallback(AccessCounter);
   25075          30 :   CHECK(current->Global()
   25076             :             ->Set(current.local(), v8_str("friend"),
   25077             :                   templ->NewInstance(current.local()).ToLocalChecked())
   25078             :             .FromJust());
   25079             : 
   25080             :   // Test access using __proto__ from the prototype chain.
   25081           5 :   access_count = 0;
   25082             :   CompileRun("friend.__proto__ = {};");
   25083           5 :   CHECK_EQ(2, access_count);
   25084             :   CompileRun("friend.__proto__;");
   25085           5 :   CHECK_EQ(4, access_count);
   25086             : 
   25087             :   // Test access using __proto__ as a hijacked function (A).
   25088           5 :   access_count = 0;
   25089             :   CompileRun("var p = Object.prototype;"
   25090             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   25091             :              "f.call(friend, {});");
   25092           5 :   CHECK_EQ(1, access_count);
   25093             :   CompileRun("var p = Object.prototype;"
   25094             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   25095             :              "f.call(friend);");
   25096           5 :   CHECK_EQ(2, access_count);
   25097             : 
   25098             :   // Test access using __proto__ as a hijacked function (B).
   25099           5 :   access_count = 0;
   25100             :   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   25101             :              "f.call(friend, {});");
   25102           5 :   CHECK_EQ(1, access_count);
   25103             :   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   25104             :              "f.call(friend);");
   25105           5 :   CHECK_EQ(2, access_count);
   25106             : 
   25107             :   // Test access using Object.setPrototypeOf reflective method.
   25108           5 :   access_count = 0;
   25109             :   CompileRun("Object.setPrototypeOf(friend, {});");
   25110           5 :   CHECK_EQ(1, access_count);
   25111             :   CompileRun("Object.getPrototypeOf(friend);");
   25112          10 :   CHECK_EQ(2, access_count);
   25113           5 : }
   25114             : 
   25115             : 
   25116       28342 : TEST(CaptureStackTraceForStackOverflow) {
   25117           5 :   v8::internal::FLAG_stack_size = 150;
   25118           5 :   LocalContext current;
   25119           5 :   v8::Isolate* isolate = current->GetIsolate();
   25120          10 :   v8::HandleScope scope(isolate);
   25121             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
   25122           5 :                                                      v8::StackTrace::kDetailed);
   25123          10 :   v8::TryCatch try_catch(isolate);
   25124             :   CompileRun("(function f(x) { f(x+1); })(0)");
   25125          10 :   CHECK(try_catch.HasCaught());
   25126           5 : }
   25127             : 
   25128             : namespace {
   25129           5 : bool ValueEqualsString(v8::Isolate* isolate, Local<Value> lhs,
   25130             :                        const char* rhs) {
   25131           5 :   CHECK(!lhs.IsEmpty());
   25132           5 :   CHECK(lhs->IsString());
   25133           5 :   String::Utf8Value utf8_lhs(isolate, lhs);
   25134           5 :   return strcmp(rhs, *utf8_lhs) == 0;
   25135             : }
   25136             : }  // namespace
   25137             : 
   25138       28342 : TEST(ScriptNameAndLineNumber) {
   25139           5 :   LocalContext env;
   25140           5 :   v8::Isolate* isolate = env->GetIsolate();
   25141          10 :   v8::HandleScope scope(isolate);
   25142             :   const char* url = "http://www.foo.com/foo.js";
   25143           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   25144           5 :   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   25145             : 
   25146             :   Local<Script> script =
   25147           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   25148          10 :   CHECK(ValueEqualsString(isolate, script->GetUnboundScript()->GetScriptName(),
   25149             :                           url));
   25150             : 
   25151          10 :   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   25152          10 :   CHECK_EQ(13, line_number);
   25153           5 : }
   25154             : 
   25155       28342 : TEST(ScriptPositionInfo) {
   25156           5 :   LocalContext env;
   25157           5 :   v8::Isolate* isolate = env->GetIsolate();
   25158             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   25159          10 :   v8::HandleScope scope(isolate);
   25160             :   const char* url = "http://www.foo.com/foo.js";
   25161           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   25162             :   v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
   25163             :                                                   "var bar;\n"
   25164             :                                                   "var fisk = foo + bar;\n"),
   25165           5 :                                            origin);
   25166             :   Local<Script> script =
   25167           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   25168             : 
   25169             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   25170          10 :       v8::Utils::OpenHandle(*script->GetUnboundScript()));
   25171          10 :   CHECK(obj->script()->IsScript());
   25172             : 
   25173          10 :   i::Handle<i::Script> script1(i::Script::cast(obj->script()), i_isolate);
   25174             : 
   25175             :   v8::internal::Script::PositionInfo info;
   25176             : 
   25177          15 :   for (int i = 0; i < 2; ++i) {
   25178             :     // With offset.
   25179             : 
   25180             :     // Behave as if 0 was passed if position is negative.
   25181          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
   25182          10 :     CHECK_EQ(13, info.line);
   25183          10 :     CHECK_EQ(0, info.column);
   25184          10 :     CHECK_EQ(0, info.line_start);
   25185          10 :     CHECK_EQ(8, info.line_end);
   25186             : 
   25187          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
   25188          10 :     CHECK_EQ(13, info.line);
   25189          10 :     CHECK_EQ(0, info.column);
   25190          10 :     CHECK_EQ(0, info.line_start);
   25191          10 :     CHECK_EQ(8, info.line_end);
   25192             : 
   25193          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
   25194          10 :     CHECK_EQ(13, info.line);
   25195          10 :     CHECK_EQ(8, info.column);
   25196          10 :     CHECK_EQ(0, info.line_start);
   25197          10 :     CHECK_EQ(8, info.line_end);
   25198             : 
   25199          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
   25200          10 :     CHECK_EQ(14, info.line);
   25201          10 :     CHECK_EQ(0, info.column);
   25202          10 :     CHECK_EQ(9, info.line_start);
   25203          10 :     CHECK_EQ(17, info.line_end);
   25204             : 
   25205             :     // Fail when position is larger than script size.
   25206          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
   25207             : 
   25208             :     // Without offset.
   25209             : 
   25210             :     // Behave as if 0 was passed if position is negative.
   25211          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
   25212          10 :     CHECK_EQ(0, info.line);
   25213          10 :     CHECK_EQ(0, info.column);
   25214          10 :     CHECK_EQ(0, info.line_start);
   25215          10 :     CHECK_EQ(8, info.line_end);
   25216             : 
   25217          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
   25218          10 :     CHECK_EQ(0, info.line);
   25219          10 :     CHECK_EQ(0, info.column);
   25220          10 :     CHECK_EQ(0, info.line_start);
   25221          10 :     CHECK_EQ(8, info.line_end);
   25222             : 
   25223          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
   25224          10 :     CHECK_EQ(0, info.line);
   25225          10 :     CHECK_EQ(8, info.column);
   25226          10 :     CHECK_EQ(0, info.line_start);
   25227          10 :     CHECK_EQ(8, info.line_end);
   25228             : 
   25229          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
   25230          10 :     CHECK_EQ(1, info.line);
   25231          10 :     CHECK_EQ(0, info.column);
   25232          10 :     CHECK_EQ(9, info.line_start);
   25233          10 :     CHECK_EQ(17, info.line_end);
   25234             : 
   25235             :     // Fail when position is larger than script size.
   25236          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
   25237             : 
   25238          10 :     i::Script::InitLineEnds(script1);
   25239           5 :   }
   25240           5 : }
   25241             : 
   25242         155 : void CheckMagicComments(v8::Isolate* isolate, Local<Script> script,
   25243             :                         const char* expected_source_url,
   25244             :                         const char* expected_source_mapping_url) {
   25245         155 :   if (expected_source_url != nullptr) {
   25246             :     v8::String::Utf8Value url(isolate,
   25247          70 :                               script->GetUnboundScript()->GetSourceURL());
   25248          35 :     CHECK_EQ(0, strcmp(expected_source_url, *url));
   25249             :   } else {
   25250         360 :     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   25251             :   }
   25252         155 :   if (expected_source_mapping_url != nullptr) {
   25253             :     v8::String::Utf8Value url(
   25254          60 :         isolate, script->GetUnboundScript()->GetSourceMappingURL());
   25255          30 :     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
   25256             :   } else {
   25257         375 :     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   25258             :   }
   25259         155 : }
   25260             : 
   25261          70 : void SourceURLHelper(v8::Isolate* isolate, const char* source,
   25262             :                      const char* expected_source_url,
   25263             :                      const char* expected_source_mapping_url) {
   25264          70 :   Local<Script> script = v8_compile(source);
   25265             :   CheckMagicComments(isolate, script, expected_source_url,
   25266          70 :                      expected_source_mapping_url);
   25267          70 : }
   25268             : 
   25269             : 
   25270       28342 : TEST(ScriptSourceURLAndSourceMappingURL) {
   25271           5 :   LocalContext env;
   25272           5 :   v8::Isolate* isolate = env->GetIsolate();
   25273          10 :   v8::HandleScope scope(isolate);
   25274             :   SourceURLHelper(isolate,
   25275             :                   "function foo() {}\n"
   25276             :                   "//# sourceURL=bar1.js\n",
   25277           5 :                   "bar1.js", nullptr);
   25278             :   SourceURLHelper(isolate,
   25279             :                   "function foo() {}\n"
   25280             :                   "//# sourceMappingURL=bar2.js\n",
   25281           5 :                   nullptr, "bar2.js");
   25282             : 
   25283             :   // Both sourceURL and sourceMappingURL.
   25284             :   SourceURLHelper(isolate,
   25285             :                   "function foo() {}\n"
   25286             :                   "//# sourceURL=bar3.js\n"
   25287             :                   "//# sourceMappingURL=bar4.js\n",
   25288           5 :                   "bar3.js", "bar4.js");
   25289             : 
   25290             :   // Two source URLs; the first one is ignored.
   25291             :   SourceURLHelper(isolate,
   25292             :                   "function foo() {}\n"
   25293             :                   "//# sourceURL=ignoreme.js\n"
   25294             :                   "//# sourceURL=bar5.js\n",
   25295           5 :                   "bar5.js", nullptr);
   25296             :   SourceURLHelper(isolate,
   25297             :                   "function foo() {}\n"
   25298             :                   "//# sourceMappingURL=ignoreme.js\n"
   25299             :                   "//# sourceMappingURL=bar6.js\n",
   25300           5 :                   nullptr, "bar6.js");
   25301             : 
   25302             :   // SourceURL or sourceMappingURL in the middle of the script.
   25303             :   SourceURLHelper(isolate,
   25304             :                   "function foo() {}\n"
   25305             :                   "//# sourceURL=bar7.js\n"
   25306             :                   "function baz() {}\n",
   25307           5 :                   "bar7.js", nullptr);
   25308             :   SourceURLHelper(isolate,
   25309             :                   "function foo() {}\n"
   25310             :                   "//# sourceMappingURL=bar8.js\n"
   25311             :                   "function baz() {}\n",
   25312           5 :                   nullptr, "bar8.js");
   25313             : 
   25314             :   // Too much whitespace.
   25315             :   SourceURLHelper(isolate,
   25316             :                   "function foo() {}\n"
   25317             :                   "//#  sourceURL=bar9.js\n"
   25318             :                   "//#  sourceMappingURL=bar10.js\n",
   25319           5 :                   nullptr, nullptr);
   25320             :   SourceURLHelper(isolate,
   25321             :                   "function foo() {}\n"
   25322             :                   "//# sourceURL =bar11.js\n"
   25323             :                   "//# sourceMappingURL =bar12.js\n",
   25324           5 :                   nullptr, nullptr);
   25325             : 
   25326             :   // Disallowed characters in value.
   25327             :   SourceURLHelper(isolate,
   25328             :                   "function foo() {}\n"
   25329             :                   "//# sourceURL=bar13 .js   \n"
   25330             :                   "//# sourceMappingURL=bar14 .js \n",
   25331           5 :                   nullptr, nullptr);
   25332             :   SourceURLHelper(isolate,
   25333             :                   "function foo() {}\n"
   25334             :                   "//# sourceURL=bar15\t.js   \n"
   25335             :                   "//# sourceMappingURL=bar16\t.js \n",
   25336           5 :                   nullptr, nullptr);
   25337             :   SourceURLHelper(isolate,
   25338             :                   "function foo() {}\n"
   25339             :                   "//# sourceURL=bar17'.js   \n"
   25340             :                   "//# sourceMappingURL=bar18'.js \n",
   25341           5 :                   nullptr, nullptr);
   25342             :   SourceURLHelper(isolate,
   25343             :                   "function foo() {}\n"
   25344             :                   "//# sourceURL=bar19\".js   \n"
   25345             :                   "//# sourceMappingURL=bar20\".js \n",
   25346           5 :                   nullptr, nullptr);
   25347             : 
   25348             :   // Not too much whitespace.
   25349             :   SourceURLHelper(isolate,
   25350             :                   "function foo() {}\n"
   25351             :                   "//# sourceURL=  bar21.js   \n"
   25352             :                   "//# sourceMappingURL=  bar22.js \n",
   25353          10 :                   "bar21.js", "bar22.js");
   25354           5 : }
   25355             : 
   25356             : 
   25357       28342 : TEST(GetOwnPropertyDescriptor) {
   25358           5 :   LocalContext env;
   25359           5 :   v8::Isolate* isolate = env->GetIsolate();
   25360          10 :   v8::HandleScope scope(isolate);
   25361             :   CompileRun(
   25362             :       "var x = { value : 13};"
   25363             :       "Object.defineProperty(x, 'p0', {value : 12});"
   25364             :       "Object.defineProperty(x, Symbol.toStringTag, {value: 'foo'});"
   25365             :       "Object.defineProperty(x, 'p1', {"
   25366             :       "  set : function(value) { this.value = value; },"
   25367             :       "  get : function() { return this.value; },"
   25368             :       "});");
   25369             :   Local<Object> x = Local<Object>::Cast(
   25370          25 :       env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
   25371             :   Local<Value> desc =
   25372          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
   25373           5 :           .ToLocalChecked();
   25374           5 :   CHECK(desc->IsUndefined());
   25375             :   desc =
   25376          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
   25377          25 :   CHECK(v8_num(12)
   25378             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   25379             :                                       ->Get(env.local(), v8_str("value"))
   25380             :                                       .ToLocalChecked())
   25381             :             .FromJust());
   25382             :   desc =
   25383          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
   25384             :   Local<Function> set =
   25385             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   25386          15 :                                 ->Get(env.local(), v8_str("set"))
   25387           5 :                                 .ToLocalChecked());
   25388             :   Local<Function> get =
   25389             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   25390          15 :                                 ->Get(env.local(), v8_str("get"))
   25391           5 :                                 .ToLocalChecked());
   25392          20 :   CHECK(v8_num(13)
   25393             :             ->Equals(env.local(),
   25394             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   25395             :             .FromJust());
   25396           5 :   Local<Value> args[] = {v8_num(14)};
   25397          10 :   set->Call(env.local(), x, 1, args).ToLocalChecked();
   25398          20 :   CHECK(v8_num(14)
   25399             :             ->Equals(env.local(),
   25400             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   25401             :             .FromJust());
   25402             :   desc =
   25403          15 :       x->GetOwnPropertyDescriptor(env.local(), Symbol::GetToStringTag(isolate))
   25404           5 :           .ToLocalChecked();
   25405          25 :   CHECK(v8_str("foo")
   25406             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   25407             :                                       ->Get(env.local(), v8_str("value"))
   25408             :                                       .ToLocalChecked())
   25409           5 :             .FromJust());
   25410           5 : }
   25411             : 
   25412             : 
   25413       28342 : TEST(Regress411877) {
   25414           5 :   v8::Isolate* isolate = CcTest::isolate();
   25415           5 :   v8::HandleScope handle_scope(isolate);
   25416             :   v8::Local<v8::ObjectTemplate> object_template =
   25417           5 :       v8::ObjectTemplate::New(isolate);
   25418           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   25419             : 
   25420           5 :   v8::Local<Context> context = Context::New(isolate);
   25421             :   v8::Context::Scope context_scope(context);
   25422             : 
   25423          25 :   CHECK(context->Global()
   25424             :             ->Set(context, v8_str("o"),
   25425             :                   object_template->NewInstance(context).ToLocalChecked())
   25426             :             .FromJust());
   25427           5 :   CompileRun("Object.getOwnPropertyNames(o)");
   25428           5 : }
   25429             : 
   25430             : 
   25431       28342 : TEST(GetHiddenPropertyTableAfterAccessCheck) {
   25432           5 :   v8::Isolate* isolate = CcTest::isolate();
   25433           5 :   v8::HandleScope handle_scope(isolate);
   25434             :   v8::Local<v8::ObjectTemplate> object_template =
   25435           5 :       v8::ObjectTemplate::New(isolate);
   25436           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   25437             : 
   25438           5 :   v8::Local<Context> context = Context::New(isolate);
   25439             :   v8::Context::Scope context_scope(context);
   25440             : 
   25441             :   v8::Local<v8::Object> obj =
   25442           5 :       object_template->NewInstance(context).ToLocalChecked();
   25443          20 :   obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
   25444          15 :   obj->Delete(context, v8_str("key")).FromJust();
   25445             : 
   25446             :   obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
   25447          15 :                   v8_str("hidden value 2"))
   25448          15 :       .FromJust();
   25449           5 : }
   25450             : 
   25451             : 
   25452       28342 : TEST(Regress411793) {
   25453           5 :   v8::Isolate* isolate = CcTest::isolate();
   25454           5 :   v8::HandleScope handle_scope(isolate);
   25455             :   v8::Local<v8::ObjectTemplate> object_template =
   25456           5 :       v8::ObjectTemplate::New(isolate);
   25457           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   25458             : 
   25459           5 :   v8::Local<Context> context = Context::New(isolate);
   25460             :   v8::Context::Scope context_scope(context);
   25461             : 
   25462          25 :   CHECK(context->Global()
   25463             :             ->Set(context, v8_str("o"),
   25464             :                   object_template->NewInstance(context).ToLocalChecked())
   25465             :             .FromJust());
   25466             :   CompileRun(
   25467             :       "Object.defineProperty(o, 'key', "
   25468           5 :       "    { get: function() {}, set: function() {} });");
   25469           5 : }
   25470             : 
   25471         210 : class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   25472             :  public:
   25473         105 :   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   25474             : 
   25475         405 :   size_t GetMoreData(const uint8_t** src) override {
   25476             :     // Unlike in real use cases, this function will never block.
   25477         405 :     if (chunks_[index_] == nullptr) {
   25478             :       return 0;
   25479             :     }
   25480             :     // Copy the data, since the caller takes ownership of it.
   25481         310 :     size_t len = strlen(chunks_[index_]);
   25482             :     // We don't need to zero-terminate since we return the length.
   25483         310 :     uint8_t* copy = new uint8_t[len];
   25484         310 :     memcpy(copy, chunks_[index_], len);
   25485         310 :     *src = copy;
   25486         310 :     ++index_;
   25487         310 :     return len;
   25488             :   }
   25489             : 
   25490             :   // Helper for constructing a string from chunks (the compilation needs it
   25491             :   // too).
   25492         105 :   static char* FullSourceString(const char** chunks) {
   25493             :     size_t total_len = 0;
   25494         435 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   25495         330 :       total_len += strlen(chunks[i]);
   25496             :     }
   25497         105 :     char* full_string = new char[total_len + 1];
   25498             :     size_t offset = 0;
   25499         435 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   25500         330 :       size_t len = strlen(chunks[i]);
   25501         330 :       memcpy(full_string + offset, chunks[i], len);
   25502         330 :       offset += len;
   25503             :     }
   25504         105 :     full_string[total_len] = 0;
   25505         105 :     return full_string;
   25506             :   }
   25507             : 
   25508             :  private:
   25509             :   const char** chunks_;
   25510             :   unsigned index_;
   25511             : };
   25512             : 
   25513             : 
   25514             : // Helper function for running streaming tests.
   25515          95 : void RunStreamingTest(const char** chunks,
   25516             :                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   25517             :                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   25518             :                       bool expected_success = true,
   25519             :                       const char* expected_source_url = nullptr,
   25520             :                       const char* expected_source_mapping_url = nullptr) {
   25521          95 :   LocalContext env;
   25522          95 :   v8::Isolate* isolate = env->GetIsolate();
   25523         190 :   v8::HandleScope scope(isolate);
   25524         190 :   v8::TryCatch try_catch(isolate);
   25525             : 
   25526             :   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
   25527         285 :                                             encoding);
   25528             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25529          95 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25530             : 
   25531             :   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   25532             :   // task here in the main thread.
   25533          95 :   task->Run();
   25534          95 :   delete task;
   25535             : 
   25536             :   // Possible errors are only produced while compiling.
   25537          95 :   CHECK(!try_catch.HasCaught());
   25538             : 
   25539          95 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25540          95 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25541             :   v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
   25542          95 :       env.local(), &source, v8_str(full_source), origin);
   25543          95 :   if (expected_success) {
   25544          85 :     CHECK(!script.IsEmpty());
   25545             :     v8::Local<Value> result(
   25546         170 :         script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
   25547             :     // All scripts are supposed to return the fixed value 13 when ran.
   25548         170 :     CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
   25549             :     CheckMagicComments(isolate, script.ToLocalChecked(), expected_source_url,
   25550          85 :                        expected_source_mapping_url);
   25551             :   } else {
   25552          10 :     CHECK(script.IsEmpty());
   25553          10 :     CHECK(try_catch.HasCaught());
   25554             :   }
   25555         190 :   delete[] full_source;
   25556          95 : }
   25557             : 
   25558       28342 : TEST(StreamingSimpleScript) {
   25559             :   // This script is unrealistically small, since no one chunk is enough to fill
   25560             :   // the backing buffer of Scanner, let alone overflow it.
   25561             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   25562           5 :                           nullptr};
   25563           5 :   RunStreamingTest(chunks);
   25564           5 : }
   25565             : 
   25566       28342 : TEST(StreamingScriptConstantArray) {
   25567             :   // When run with Ignition, tests that the streaming parser canonicalizes
   25568             :   // handles so that they are only added to the constant pool array once.
   25569             :   const char* chunks[] = {
   25570             :       "var a = {};",        "var b = {};", "var c = 'testing';",
   25571           5 :       "var d = 'testing';", "13;",         nullptr};
   25572           5 :   RunStreamingTest(chunks);
   25573           5 : }
   25574             : 
   25575       28342 : TEST(StreamingScriptEvalShadowing) {
   25576             :   // When run with Ignition, tests that the streaming parser canonicalizes
   25577             :   // handles so the Variable::is_possibly_eval() is correct.
   25578             :   const char* chunk1 =
   25579             :       "(function() {\n"
   25580             :       "  var y = 2;\n"
   25581             :       "  return (function() {\n"
   25582             :       "    eval('var y = 13;');\n"
   25583             :       "    function g() {\n"
   25584             :       "      return y\n"
   25585             :       "    }\n"
   25586             :       "    return g();\n"
   25587             :       "  })()\n"
   25588             :       "})()\n";
   25589           5 :   const char* chunks[] = {chunk1, nullptr};
   25590           5 :   RunStreamingTest(chunks);
   25591           5 : }
   25592             : 
   25593       28342 : TEST(StreamingBiggerScript) {
   25594             :   const char* chunk1 =
   25595             :       "function foo() {\n"
   25596             :       "  // Make this chunk sufficiently long so that it will overflow the\n"
   25597             :       "  // backing buffer of the Scanner.\n"
   25598             :       "  var i = 0;\n"
   25599             :       "  var result = 0;\n"
   25600             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25601             :       "  result = 0;\n"
   25602             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25603             :       "  result = 0;\n"
   25604             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25605             :       "  result = 0;\n"
   25606             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   25607             :       "  return result;\n"
   25608             :       "}\n";
   25609           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   25610           5 :   RunStreamingTest(chunks);
   25611           5 : }
   25612             : 
   25613             : 
   25614       28342 : TEST(StreamingScriptWithParseError) {
   25615             :   // Test that parse errors from streamed scripts are propagated correctly.
   25616             :   {
   25617             :     char chunk1[] =
   25618             :         "  // This will result in a parse error.\n"
   25619           5 :         "  var if else then foo";
   25620           5 :     char chunk2[] = "  13\n";
   25621           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25622             : 
   25623             :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   25624           5 :                      false);
   25625             :   }
   25626             :   // Test that the next script succeeds normally.
   25627             :   {
   25628             :     char chunk1[] =
   25629             :         "  // This will be parsed successfully.\n"
   25630           5 :         "  function foo() { return ";
   25631           5 :     char chunk2[] = "  13; }\n";
   25632           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25633             : 
   25634           5 :     RunStreamingTest(chunks);
   25635             :   }
   25636           5 : }
   25637             : 
   25638             : 
   25639       28342 : TEST(StreamingUtf8Script) {
   25640             :   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
   25641             :   // don't like it.
   25642             :   const char* chunk1 =
   25643             :       "function foo() {\n"
   25644             :       "  // This function will contain an UTF-8 character which is not in\n"
   25645             :       "  // ASCII.\n"
   25646             :       "  var foob\xec\x92\x81r = 13;\n"
   25647             :       "  return foob\xec\x92\x81r;\n"
   25648             :       "}\n";
   25649           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   25650           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25651           5 : }
   25652             : 
   25653             : 
   25654       28342 : TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   25655             :   // A sanity check to prove that the approach of splitting UTF-8
   25656             :   // characters is correct. Here is an UTF-8 character which will take three
   25657             :   // bytes.
   25658             :   const char* reference = "\xec\x92\x81";
   25659             :   CHECK_EQ(3, strlen(reference));
   25660             : 
   25661             :   char chunk1[] =
   25662             :       "function foo() {\n"
   25663             :       "  // This function will contain an UTF-8 character which is not in\n"
   25664             :       "  // ASCII.\n"
   25665           5 :       "  var foob";
   25666             :   char chunk2[] =
   25667             :       "XXXr = 13;\n"
   25668             :       "  return foob\xec\x92\x81r;\n"
   25669           5 :       "}\n";
   25670          20 :   for (int i = 0; i < 3; ++i) {
   25671          15 :     chunk2[i] = reference[i];
   25672             :   }
   25673           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25674           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25675           5 : }
   25676             : 
   25677             : 
   25678       28342 : TEST(StreamingUtf8ScriptWithSplitCharacters) {
   25679             :   // Stream data where a multi-byte UTF-8 character is split between two data
   25680             :   // chunks.
   25681             :   const char* reference = "\xec\x92\x81";
   25682             :   char chunk1[] =
   25683             :       "function foo() {\n"
   25684             :       "  // This function will contain an UTF-8 character which is not in\n"
   25685             :       "  // ASCII.\n"
   25686           5 :       "  var foobX";
   25687             :   char chunk2[] =
   25688             :       "XXr = 13;\n"
   25689             :       "  return foob\xec\x92\x81r;\n"
   25690           5 :       "}\n";
   25691           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25692           5 :   chunk2[0] = reference[1];
   25693           5 :   chunk2[1] = reference[2];
   25694           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25695           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25696           5 : }
   25697             : 
   25698             : 
   25699       28342 : TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   25700             :   // Tests edge cases which should still be decoded correctly.
   25701             : 
   25702             :   // Case 1: a chunk contains only bytes for a split character (and no other
   25703             :   // data). This kind of a chunk would be exceptionally small, but we should
   25704             :   // still decode it correctly.
   25705             :   const char* reference = "\xec\x92\x81";
   25706             :   // The small chunk is at the beginning of the split character
   25707             :   {
   25708             :     char chunk1[] =
   25709             :         "function foo() {\n"
   25710             :         "  // This function will contain an UTF-8 character which is not in\n"
   25711             :         "  // ASCII.\n"
   25712           5 :         "  var foob";
   25713           5 :     char chunk2[] = "XX";
   25714             :     char chunk3[] =
   25715             :         "Xr = 13;\n"
   25716             :         "  return foob\xec\x92\x81r;\n"
   25717           5 :         "}\n";
   25718           5 :     chunk2[0] = reference[0];
   25719           5 :     chunk2[1] = reference[1];
   25720           5 :     chunk3[0] = reference[2];
   25721           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25722           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25723             :   }
   25724             :   // The small chunk is at the end of a character
   25725             :   {
   25726             :     char chunk1[] =
   25727             :         "function foo() {\n"
   25728             :         "  // This function will contain an UTF-8 character which is not in\n"
   25729             :         "  // ASCII.\n"
   25730           5 :         "  var foobX";
   25731           5 :     char chunk2[] = "XX";
   25732             :     char chunk3[] =
   25733             :         "r = 13;\n"
   25734             :         "  return foob\xec\x92\x81r;\n"
   25735           5 :         "}\n";
   25736           5 :     chunk1[strlen(chunk1) - 1] = reference[0];
   25737           5 :     chunk2[0] = reference[1];
   25738           5 :     chunk2[1] = reference[2];
   25739           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25740           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25741             :   }
   25742             :   // Case 2: the script ends with a multi-byte character. Make sure that it's
   25743             :   // decoded correctly and not just ignored.
   25744             :   {
   25745             :     char chunk1[] =
   25746             :         "var foob\xec\x92\x81 = 13;\n"
   25747           5 :         "foob\xec\x92\x81";
   25748           5 :     const char* chunks[] = {chunk1, nullptr};
   25749           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25750             :   }
   25751           5 : }
   25752             : 
   25753             : 
   25754       28342 : TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   25755             :   // Test cases where a UTF-8 character is split over several chunks. Those
   25756             :   // cases are not supported (the embedder should give the data in big enough
   25757             :   // chunks), but we shouldn't crash and parse this just fine.
   25758             :   const char* reference = "\xec\x92\x81";
   25759             :   char chunk1[] =
   25760             :       "function foo() {\n"
   25761             :       "  // This function will contain an UTF-8 character which is not in\n"
   25762             :       "  // ASCII.\n"
   25763           5 :       "  var foobX";
   25764           5 :   char chunk2[] = "X";
   25765             :   char chunk3[] =
   25766             :       "Xr = 13;\n"
   25767             :       "  return foob\xec\x92\x81r;\n"
   25768           5 :       "}\n";
   25769           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25770           5 :   chunk2[0] = reference[1];
   25771           5 :   chunk3[0] = reference[2];
   25772           5 :   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25773             : 
   25774           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25775           5 : }
   25776             : 
   25777             : 
   25778             : 
   25779       28342 : TEST(StreamingWithDebuggingEnabledLate) {
   25780             :   // The streaming parser can only parse lazily, i.e. inner functions are not
   25781             :   // fully parsed. However, we may compile inner functions eagerly when
   25782             :   // debugging. Make sure that we can deal with this when turning on debugging
   25783             :   // after streaming parser has already finished parsing.
   25784             :   const char* chunks[] = {"with({x:1}) {",
   25785             :                           "  var foo = function foo(y) {",
   25786             :                           "    return x + y;",
   25787             :                           "  };",
   25788             :                           "  foo(2);",
   25789             :                           "}",
   25790           5 :                           nullptr};
   25791             : 
   25792           5 :   LocalContext env;
   25793           5 :   v8::Isolate* isolate = env->GetIsolate();
   25794          10 :   v8::HandleScope scope(isolate);
   25795          10 :   v8::TryCatch try_catch(isolate);
   25796             : 
   25797             :   v8::ScriptCompiler::StreamedSource source(
   25798             :       new TestSourceStream(chunks),
   25799          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25800             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25801           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25802             : 
   25803           5 :   task->Run();
   25804           5 :   delete task;
   25805             : 
   25806           5 :   CHECK(!try_catch.HasCaught());
   25807             : 
   25808           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25809           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25810             : 
   25811             :   EnableDebugger(isolate);
   25812             : 
   25813             :   v8::Local<Script> script =
   25814             :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25815           5 :                                   origin)
   25816           5 :           .ToLocalChecked();
   25817             : 
   25818             :   Maybe<uint32_t> result =
   25819          10 :       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
   25820           5 :   CHECK_EQ(3U, result.FromMaybe(0));
   25821             : 
   25822           5 :   delete[] full_source;
   25823             : 
   25824           5 :   DisableDebugger(isolate);
   25825           5 : }
   25826             : 
   25827             : 
   25828       28342 : TEST(StreamingScriptWithInvalidUtf8) {
   25829             :   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   25830             :   // chunk don't produce a crash.
   25831             :   const char* reference = "\xec\x92\x81\x80\x80";
   25832             :   char chunk1[] =
   25833             :       "function foo() {\n"
   25834             :       "  // This function will contain an UTF-8 character which is not in\n"
   25835             :       "  // ASCII.\n"
   25836           5 :       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   25837             :   char chunk2[] =
   25838             :       "r = 13;\n"
   25839             :       "  return foob\xec\x92\x81\x80\x80r;\n"
   25840           5 :       "}\n";
   25841           5 :   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   25842             : 
   25843           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25844           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   25845           5 : }
   25846             : 
   25847             : 
   25848       28342 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
   25849             :   // Regression test: Stream data where there are several multi-byte UTF-8
   25850             :   // characters in a sequence and one of them is split between two data chunks.
   25851             :   const char* reference = "\xec\x92\x81";
   25852             :   char chunk1[] =
   25853             :       "function foo() {\n"
   25854             :       "  // This function will contain an UTF-8 character which is not in\n"
   25855             :       "  // ASCII.\n"
   25856           5 :       "  var foob\xec\x92\x81X";
   25857             :   char chunk2[] =
   25858             :       "XXr = 13;\n"
   25859             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25860           5 :       "}\n";
   25861           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25862           5 :   chunk2[0] = reference[1];
   25863           5 :   chunk2[1] = reference[2];
   25864           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25865           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25866           5 : }
   25867             : 
   25868             : 
   25869       28342 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
   25870             :   // Another regression test, similar to the previous one. The difference is
   25871             :   // that the split character is not the last one in the sequence.
   25872             :   const char* reference = "\xec\x92\x81";
   25873             :   char chunk1[] =
   25874             :       "function foo() {\n"
   25875             :       "  // This function will contain an UTF-8 character which is not in\n"
   25876             :       "  // ASCII.\n"
   25877           5 :       "  var foobX";
   25878             :   char chunk2[] =
   25879             :       "XX\xec\x92\x81r = 13;\n"
   25880             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25881           5 :       "}\n";
   25882           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25883           5 :   chunk2[0] = reference[1];
   25884           5 :   chunk2[1] = reference[2];
   25885           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25886           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25887           5 : }
   25888             : 
   25889             : 
   25890       28342 : TEST(StreamingWithHarmonyScopes) {
   25891             :   // Don't use RunStreamingTest here so that both scripts get to use the same
   25892             :   // LocalContext and HandleScope.
   25893           5 :   LocalContext env;
   25894           5 :   v8::Isolate* isolate = env->GetIsolate();
   25895          10 :   v8::HandleScope scope(isolate);
   25896             : 
   25897             :   // First, run a script with a let variable.
   25898             :   CompileRun("\"use strict\"; let x = 1;");
   25899             : 
   25900             :   // Then stream a script which (erroneously) tries to introduce the same
   25901             :   // variable again.
   25902           5 :   const char* chunks[] = {"\"use strict\"; let x = 2;", nullptr};
   25903             : 
   25904          10 :   v8::TryCatch try_catch(isolate);
   25905             :   v8::ScriptCompiler::StreamedSource source(
   25906             :       new TestSourceStream(chunks),
   25907          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25908             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25909           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25910           5 :   task->Run();
   25911           5 :   delete task;
   25912             : 
   25913             :   // Parsing should succeed (the script will be parsed and compiled in a context
   25914             :   // independent way, so the error is not detected).
   25915           5 :   CHECK(!try_catch.HasCaught());
   25916             : 
   25917           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25918           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25919             :   v8::Local<Script> script =
   25920             :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25921           5 :                                   origin)
   25922           5 :           .ToLocalChecked();
   25923           5 :   CHECK(!script.IsEmpty());
   25924           5 :   CHECK(!try_catch.HasCaught());
   25925             : 
   25926             :   // Running the script exposes the error.
   25927          10 :   CHECK(script->Run(env.local()).IsEmpty());
   25928           5 :   CHECK(try_catch.HasCaught());
   25929          10 :   delete[] full_source;
   25930           5 : }
   25931             : 
   25932             : 
   25933       28342 : TEST(CodeCache) {
   25934             :   v8::Isolate::CreateParams create_params;
   25935           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25936             : 
   25937             :   const char* source = "Math.sqrt(4)";
   25938             :   const char* origin = "code cache test";
   25939             :   v8::ScriptCompiler::CachedData* cache;
   25940             : 
   25941           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   25942             :   {
   25943             :     v8::Isolate::Scope iscope(isolate1);
   25944          10 :     v8::HandleScope scope(isolate1);
   25945           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   25946             :     v8::Context::Scope cscope(context);
   25947           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25948           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25949             :     v8::ScriptCompiler::Source source(source_string, script_origin);
   25950             :     v8::ScriptCompiler::CompileOptions option =
   25951             :         v8::ScriptCompiler::kNoCompileOptions;
   25952             :     v8::Local<v8::Script> script =
   25953           5 :         v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25954           5 :     cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
   25955             :   }
   25956           5 :   isolate1->Dispose();
   25957             : 
   25958           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   25959             :   {
   25960             :     v8::Isolate::Scope iscope(isolate2);
   25961          10 :     v8::HandleScope scope(isolate2);
   25962           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   25963             :     v8::Context::Scope cscope(context);
   25964           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25965           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25966             :     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
   25967             :     v8::ScriptCompiler::CompileOptions option =
   25968             :         v8::ScriptCompiler::kConsumeCodeCache;
   25969             :     v8::Local<v8::Script> script;
   25970             :     {
   25971             :       i::DisallowCompilation no_compile(
   25972             :           reinterpret_cast<i::Isolate*>(isolate2));
   25973             :       script = v8::ScriptCompiler::Compile(context, &source, option)
   25974           5 :                    .ToLocalChecked();
   25975             :     }
   25976          20 :     CHECK_EQ(2, script->Run(context)
   25977             :                     .ToLocalChecked()
   25978             :                     ->ToInt32(context)
   25979             :                     .ToLocalChecked()
   25980             :                     ->Int32Value(context)
   25981             :                     .FromJust());
   25982             :   }
   25983           5 :   isolate2->Dispose();
   25984           5 : }
   25985             : 
   25986           0 : v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
   25987             :                                                        Local<String> specifier,
   25988             :                                                        Local<Module> referrer) {
   25989           0 :   CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
   25990             : }
   25991             : 
   25992             : namespace {
   25993             : 
   25994          10 : Local<Module> CompileAndInstantiateModule(v8::Isolate* isolate,
   25995             :                                           Local<Context> context,
   25996             :                                           const char* resource_name,
   25997             :                                           const char* source) {
   25998          10 :   Local<String> source_string = v8_str(source);
   25999             :   v8::ScriptOrigin script_origin(
   26000             :       v8_str(resource_name), Local<v8::Integer>(), Local<v8::Integer>(),
   26001             :       Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   26002          10 :       Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   26003             :   v8::ScriptCompiler::Source script_compiler_source(source_string,
   26004             :                                                     script_origin);
   26005             :   Local<Module> module =
   26006             :       v8::ScriptCompiler::CompileModule(isolate, &script_compiler_source)
   26007          10 :           .ToLocalChecked();
   26008             :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   26009          20 :       .ToChecked();
   26010             : 
   26011          20 :   return module;
   26012             : }
   26013             : 
   26014           5 : Local<Module> CompileAndInstantiateModuleFromCache(
   26015             :     v8::Isolate* isolate, Local<Context> context, const char* resource_name,
   26016             :     const char* source, v8::ScriptCompiler::CachedData* cache) {
   26017           5 :   Local<String> source_string = v8_str(source);
   26018             :   v8::ScriptOrigin script_origin(
   26019             :       v8_str(resource_name), Local<v8::Integer>(), Local<v8::Integer>(),
   26020             :       Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   26021           5 :       Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   26022             :   v8::ScriptCompiler::Source script_compiler_source(source_string,
   26023             :                                                     script_origin, cache);
   26024             : 
   26025             :   Local<Module> module =
   26026             :       v8::ScriptCompiler::CompileModule(isolate, &script_compiler_source,
   26027             :                                         v8::ScriptCompiler::kConsumeCodeCache)
   26028           5 :           .ToLocalChecked();
   26029             :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   26030          10 :       .ToChecked();
   26031             : 
   26032          10 :   return module;
   26033             : }
   26034             : 
   26035             : }  // namespace
   26036             : 
   26037       28342 : TEST(ModuleCodeCache) {
   26038             :   v8::Isolate::CreateParams create_params;
   26039           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   26040             : 
   26041             :   const char* origin = "code cache test";
   26042             :   const char* source =
   26043             :       "export default 5; export const a = 10; function f() { return 42; } "
   26044             :       "(function() { return f(); })();";
   26045             : 
   26046             :   v8::ScriptCompiler::CachedData* cache;
   26047             :   {
   26048           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   26049             :     {
   26050             :       v8::Isolate::Scope iscope(isolate);
   26051          10 :       v8::HandleScope scope(isolate);
   26052           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   26053             :       v8::Context::Scope cscope(context);
   26054             : 
   26055             :       Local<Module> module =
   26056           5 :           CompileAndInstantiateModule(isolate, context, origin, source);
   26057             : 
   26058             :       // Fetch the shared function info before evaluation.
   26059             :       Local<v8::UnboundModuleScript> unbound_module_script =
   26060           5 :           module->GetUnboundModuleScript();
   26061             : 
   26062             :       // Evaluate for possible lazy compilation.
   26063             :       Local<Value> completion_value =
   26064           5 :           module->Evaluate(context).ToLocalChecked();
   26065          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   26066             : 
   26067             :       // Now create the cache. Note that it is freed, obscurely, when
   26068             :       // ScriptCompiler::Source goes out of scope below.
   26069           5 :       cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
   26070             :     }
   26071           5 :     isolate->Dispose();
   26072             :   }
   26073             : 
   26074             :   // Test that the cache is consumed and execution still works.
   26075             :   {
   26076             :     // Disable --always_opt, otherwise we try to optimize during module
   26077             :     // instantiation, violating the DisallowCompilation scope.
   26078           5 :     i::FLAG_always_opt = false;
   26079           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   26080             :     {
   26081             :       v8::Isolate::Scope iscope(isolate);
   26082          10 :       v8::HandleScope scope(isolate);
   26083           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   26084             :       v8::Context::Scope cscope(context);
   26085             : 
   26086             :       Local<Module> module;
   26087             :       {
   26088             :         i::DisallowCompilation no_compile(
   26089             :             reinterpret_cast<i::Isolate*>(isolate));
   26090             :         module = CompileAndInstantiateModuleFromCache(isolate, context, origin,
   26091           5 :                                                       source, cache);
   26092             :       }
   26093             : 
   26094             :       Local<Value> completion_value =
   26095           5 :           module->Evaluate(context).ToLocalChecked();
   26096          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   26097             :     }
   26098           5 :     isolate->Dispose();
   26099             :   }
   26100           5 : }
   26101             : 
   26102             : // Tests that the code cache does not confuse the same source code compiled as a
   26103             : // script and as a module.
   26104       28342 : TEST(CodeCacheModuleScriptMismatch) {
   26105             :   v8::Isolate::CreateParams create_params;
   26106           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   26107             : 
   26108             :   const char* origin = "code cache test";
   26109             :   const char* source = "42";
   26110             : 
   26111             :   v8::ScriptCompiler::CachedData* cache;
   26112             :   {
   26113           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   26114             :     {
   26115             :       v8::Isolate::Scope iscope(isolate);
   26116          10 :       v8::HandleScope scope(isolate);
   26117           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   26118             :       v8::Context::Scope cscope(context);
   26119             : 
   26120             :       Local<Module> module =
   26121           5 :           CompileAndInstantiateModule(isolate, context, origin, source);
   26122             : 
   26123             :       // Fetch the shared function info before evaluation.
   26124             :       Local<v8::UnboundModuleScript> unbound_module_script =
   26125           5 :           module->GetUnboundModuleScript();
   26126             : 
   26127             :       // Evaluate for possible lazy compilation.
   26128             :       Local<Value> completion_value =
   26129           5 :           module->Evaluate(context).ToLocalChecked();
   26130          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   26131             : 
   26132             :       // Now create the cache. Note that it is freed, obscurely, when
   26133             :       // ScriptCompiler::Source goes out of scope below.
   26134           5 :       cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
   26135             :     }
   26136           5 :     isolate->Dispose();
   26137             :   }
   26138             : 
   26139             :   // Test that the cache is not consumed when source is compiled as a script.
   26140             :   {
   26141           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   26142             :     {
   26143             :       v8::Isolate::Scope iscope(isolate);
   26144          10 :       v8::HandleScope scope(isolate);
   26145           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   26146             :       v8::Context::Scope cscope(context);
   26147             : 
   26148           5 :       v8::ScriptOrigin script_origin(v8_str(origin));
   26149             :       v8::ScriptCompiler::Source script_compiler_source(v8_str(source),
   26150           5 :                                                         script_origin, cache);
   26151             : 
   26152             :       v8::Local<v8::Script> script =
   26153             :           v8::ScriptCompiler::Compile(context, &script_compiler_source,
   26154             :                                       v8::ScriptCompiler::kConsumeCodeCache)
   26155           5 :               .ToLocalChecked();
   26156             : 
   26157           5 :       CHECK(cache->rejected);
   26158             : 
   26159          20 :       CHECK_EQ(42, script->Run(context)
   26160             :                        .ToLocalChecked()
   26161             :                        ->ToInt32(context)
   26162             :                        .ToLocalChecked()
   26163             :                        ->Int32Value(context)
   26164             :                        .FromJust());
   26165             :     }
   26166           5 :     isolate->Dispose();
   26167             :   }
   26168           5 : }
   26169             : 
   26170             : // Same as above but other way around.
   26171       28342 : TEST(CodeCacheScriptModuleMismatch) {
   26172             :   v8::Isolate::CreateParams create_params;
   26173           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   26174             : 
   26175             :   const char* origin = "code cache test";
   26176             :   const char* source = "42";
   26177             : 
   26178             :   v8::ScriptCompiler::CachedData* cache;
   26179             :   {
   26180           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   26181             :     {
   26182             :       v8::Isolate::Scope iscope(isolate);
   26183          10 :       v8::HandleScope scope(isolate);
   26184           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   26185             :       v8::Context::Scope cscope(context);
   26186           5 :       v8::Local<v8::String> source_string = v8_str(source);
   26187           5 :       v8::ScriptOrigin script_origin(v8_str(origin));
   26188             :       v8::ScriptCompiler::Source source(source_string, script_origin);
   26189             :       v8::ScriptCompiler::CompileOptions option =
   26190             :           v8::ScriptCompiler::kNoCompileOptions;
   26191             :       v8::Local<v8::Script> script =
   26192             :           v8::ScriptCompiler::Compile(context, &source, option)
   26193           5 :               .ToLocalChecked();
   26194           5 :       cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
   26195             :     }
   26196           5 :     isolate->Dispose();
   26197             :   }
   26198             : 
   26199             :   // Test that the cache is not consumed when source is compiled as a module.
   26200             :   {
   26201           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   26202             :     {
   26203             :       v8::Isolate::Scope iscope(isolate);
   26204          10 :       v8::HandleScope scope(isolate);
   26205           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   26206             :       v8::Context::Scope cscope(context);
   26207             : 
   26208             :       v8::ScriptOrigin script_origin(
   26209             :           v8_str(origin), Local<v8::Integer>(), Local<v8::Integer>(),
   26210             :           Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   26211           5 :           Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   26212             :       v8::ScriptCompiler::Source script_compiler_source(v8_str(source),
   26213           5 :                                                         script_origin, cache);
   26214             : 
   26215             :       Local<Module> module = v8::ScriptCompiler::CompileModule(
   26216             :                                  isolate, &script_compiler_source,
   26217             :                                  v8::ScriptCompiler::kConsumeCodeCache)
   26218           5 :                                  .ToLocalChecked();
   26219             :       module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   26220          10 :           .ToChecked();
   26221             : 
   26222           5 :       CHECK(cache->rejected);
   26223             : 
   26224             :       Local<Value> completion_value =
   26225           5 :           module->Evaluate(context).ToLocalChecked();
   26226          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   26227             :     }
   26228           5 :     isolate->Dispose();
   26229             :   }
   26230           5 : }
   26231             : 
   26232             : // Tests that compilation can handle a garbled cache.
   26233       28342 : TEST(InvalidCodeCacheDataInCompileModule) {
   26234           5 :   v8::V8::Initialize();
   26235           5 :   v8::Isolate* isolate = CcTest::isolate();
   26236           5 :   v8::HandleScope scope(isolate);
   26237          10 :   LocalContext local_context;
   26238             : 
   26239             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   26240             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   26241           5 :   Local<String> origin = v8_str("origin");
   26242             :   int length = 16;
   26243             :   v8::ScriptCompiler::CachedData* cached_data =
   26244           5 :       new v8::ScriptCompiler::CachedData(data, length);
   26245           5 :   CHECK(!cached_data->rejected);
   26246             : 
   26247             :   v8::ScriptOrigin script_origin(
   26248             :       origin, Local<v8::Integer>(), Local<v8::Integer>(), Local<v8::Boolean>(),
   26249             :       Local<v8::Integer>(), Local<v8::Value>(), Local<v8::Boolean>(),
   26250             :       Local<v8::Boolean>(), True(isolate));
   26251           5 :   v8::ScriptCompiler::Source source(v8_str("42"), script_origin, cached_data);
   26252           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   26253             : 
   26254             :   Local<Module> module =
   26255             :       v8::ScriptCompiler::CompileModule(isolate, &source,
   26256             :                                         v8::ScriptCompiler::kConsumeCodeCache)
   26257           5 :           .ToLocalChecked();
   26258             :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   26259          10 :       .ToChecked();
   26260             : 
   26261           5 :   CHECK(cached_data->rejected);
   26262          15 :   CHECK_EQ(42, module->Evaluate(context)
   26263             :                    .ToLocalChecked()
   26264             :                    ->Int32Value(context)
   26265           5 :                    .FromJust());
   26266           5 : }
   26267             : 
   26268           5 : void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
   26269             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   26270             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   26271             :   int length = 16;
   26272             :   v8::ScriptCompiler::CachedData* cached_data =
   26273           5 :       new v8::ScriptCompiler::CachedData(data, length);
   26274           5 :   CHECK(!cached_data->rejected);
   26275           5 :   v8::ScriptOrigin origin(v8_str("origin"));
   26276           5 :   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
   26277           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   26278             :   v8::Local<v8::Script> script =
   26279           5 :       v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   26280           5 :   CHECK(cached_data->rejected);
   26281          15 :   CHECK_EQ(
   26282             :       42,
   26283             :       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
   26284           5 : }
   26285             : 
   26286             : 
   26287       28342 : TEST(InvalidCodeCacheData) {
   26288           5 :   v8::V8::Initialize();
   26289           5 :   v8::HandleScope scope(CcTest::isolate());
   26290          10 :   LocalContext context;
   26291          10 :   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
   26292           5 : }
   26293             : 
   26294             : 
   26295       28342 : TEST(StringConcatOverflow) {
   26296           5 :   v8::V8::Initialize();
   26297           5 :   v8::Isolate* isolate = CcTest::isolate();
   26298           5 :   v8::HandleScope scope(isolate);
   26299             :   RandomLengthOneByteResource* r =
   26300           5 :       new RandomLengthOneByteResource(i::String::kMaxLength);
   26301             :   v8::Local<v8::String> str =
   26302           5 :       v8::String::NewExternalOneByte(isolate, r).ToLocalChecked();
   26303           5 :   CHECK(!str.IsEmpty());
   26304          10 :   v8::TryCatch try_catch(isolate);
   26305           5 :   v8::Local<v8::String> result = v8::String::Concat(isolate, str, str);
   26306           5 :   v8::String::Concat(CcTest::isolate(), str, str);
   26307           5 :   CHECK(result.IsEmpty());
   26308          10 :   CHECK(!try_catch.HasCaught());
   26309           5 : }
   26310             : 
   26311       28342 : TEST(TurboAsmDisablesDetach) {
   26312             : #ifndef V8_LITE_MODE
   26313           5 :   i::FLAG_opt = true;
   26314           5 :   i::FLAG_allow_natives_syntax = true;
   26315           5 :   v8::V8::Initialize();
   26316           5 :   v8::HandleScope scope(CcTest::isolate());
   26317          10 :   LocalContext context;
   26318             :   const char* load =
   26319             :       "function Module(stdlib, foreign, heap) {"
   26320             :       "  'use asm';"
   26321             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   26322             :       "  function load() { return MEM32[0] | 0; }"
   26323             :       "  return { load: load };"
   26324             :       "}"
   26325             :       "var buffer = new ArrayBuffer(4096);"
   26326             :       "var module = Module(this, {}, buffer);"
   26327             :       "%OptimizeFunctionOnNextCall(module.load);"
   26328             :       "module.load();"
   26329             :       "buffer";
   26330             : 
   26331             :   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   26332           5 :   CHECK(!result->IsDetachable());
   26333             : 
   26334             :   const char* store =
   26335             :       "function Module(stdlib, foreign, heap) {"
   26336             :       "  'use asm';"
   26337             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   26338             :       "  function store() { MEM32[0] = 0; }"
   26339             :       "  return { store: store };"
   26340             :       "}"
   26341             :       "var buffer = new ArrayBuffer(4096);"
   26342             :       "var module = Module(this, {}, buffer);"
   26343             :       "%OptimizeFunctionOnNextCall(module.store);"
   26344             :       "module.store();"
   26345             :       "buffer";
   26346             : 
   26347             :   result = CompileRun(store).As<v8::ArrayBuffer>();
   26348          10 :   CHECK(!result->IsDetachable());
   26349             : #endif  // V8_LITE_MODE
   26350           5 : }
   26351             : 
   26352       28342 : TEST(ClassPrototypeCreationContext) {
   26353           5 :   v8::Isolate* isolate = CcTest::isolate();
   26354           5 :   v8::HandleScope handle_scope(isolate);
   26355          10 :   LocalContext env;
   26356             : 
   26357             :   Local<Object> result = Local<Object>::Cast(
   26358             :       CompileRun("'use strict'; class Example { }; Example.prototype"));
   26359          15 :   CHECK(env.local() == result->CreationContext());
   26360           5 : }
   26361             : 
   26362             : 
   26363       28342 : TEST(SimpleStreamingScriptWithSourceURL) {
   26364             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
   26365           5 :                           "//# sourceURL=bar2.js\n", nullptr};
   26366             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   26367           5 :                    "bar2.js");
   26368           5 : }
   26369             : 
   26370             : 
   26371       28342 : TEST(StreamingScriptWithSplitSourceURL) {
   26372             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
   26373           5 :                           "oo();\n//# sourceURL=b", "ar2.js\n", nullptr};
   26374             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   26375           5 :                    "bar2.js");
   26376           5 : }
   26377             : 
   26378             : 
   26379       28342 : TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
   26380             :   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
   26381           5 :                           " sourceMappingURL=bar2.js\n", "foo();", nullptr};
   26382             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   26383           5 :                    nullptr, "bar2.js");
   26384           5 : }
   26385             : 
   26386             : 
   26387       28342 : TEST(NewStringRangeError) {
   26388             :   // This test uses a lot of memory and fails with flaky OOM when run
   26389             :   // with --stress-incremental-marking on TSAN.
   26390           5 :   i::FLAG_stress_incremental_marking = false;
   26391           5 :   v8::Isolate* isolate = CcTest::isolate();
   26392           5 :   v8::HandleScope handle_scope(isolate);
   26393             :   const int length = i::String::kMaxLength + 1;
   26394             :   const int buffer_size = length * sizeof(uint16_t);
   26395           5 :   void* buffer = malloc(buffer_size);
   26396           5 :   if (buffer == nullptr) return;
   26397             :   memset(buffer, 'A', buffer_size);
   26398             :   {
   26399           5 :     v8::TryCatch try_catch(isolate);
   26400             :     char* data = reinterpret_cast<char*>(buffer);
   26401          10 :     CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
   26402             :                                   length)
   26403             :               .IsEmpty());
   26404           5 :     CHECK(!try_catch.HasCaught());
   26405             :   }
   26406             :   {
   26407           5 :     v8::TryCatch try_catch(isolate);
   26408             :     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
   26409          10 :     CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
   26410             :                                      length)
   26411             :               .IsEmpty());
   26412           5 :     CHECK(!try_catch.HasCaught());
   26413             :   }
   26414             :   {
   26415           5 :     v8::TryCatch try_catch(isolate);
   26416             :     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
   26417          10 :     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
   26418             :                                      length)
   26419             :               .IsEmpty());
   26420           5 :     CHECK(!try_catch.HasCaught());
   26421             :   }
   26422           5 :   free(buffer);
   26423             : }
   26424             : 
   26425             : 
   26426       28337 : TEST(SealHandleScope) {
   26427           0 :   v8::Isolate* isolate = CcTest::isolate();
   26428           0 :   v8::HandleScope handle_scope(isolate);
   26429           0 :   LocalContext env;
   26430             : 
   26431           0 :   v8::SealHandleScope seal(isolate);
   26432             : 
   26433             :   // Should fail
   26434           0 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   26435             : 
   26436           0 :   USE(obj);
   26437           0 : }
   26438             : 
   26439             : 
   26440       28342 : TEST(SealHandleScopeNested) {
   26441           5 :   v8::Isolate* isolate = CcTest::isolate();
   26442           5 :   v8::HandleScope handle_scope(isolate);
   26443          10 :   LocalContext env;
   26444             : 
   26445          10 :   v8::SealHandleScope seal(isolate);
   26446             : 
   26447             :   {
   26448           5 :     v8::HandleScope handle_scope(isolate);
   26449             : 
   26450             :     // Should work
   26451           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   26452             : 
   26453           5 :     USE(obj);
   26454           5 :   }
   26455           5 : }
   26456             : 
   26457             : 
   26458           5 : static void ExtrasBindingTestRuntimeFunction(
   26459          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   26460          15 :   CHECK_EQ(
   26461             :       3,
   26462             :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
   26463           5 :   args.GetReturnValue().Set(v8_num(7));
   26464           5 : }
   26465             : 
   26466       28342 : TEST(ExtrasFunctionSource) {
   26467           5 :   v8::Isolate* isolate = CcTest::isolate();
   26468           5 :   v8::HandleScope handle_scope(isolate);
   26469          10 :   LocalContext env;
   26470             : 
   26471           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26472             : 
   26473             :   // Functions defined in extras do not expose source code.
   26474          15 :   auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
   26475           5 :                   .ToLocalChecked()
   26476             :                   .As<v8::Function>();
   26477             :   auto undefined = v8::Undefined(isolate);
   26478          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   26479           5 :                     .ToLocalChecked()
   26480             :                     .As<v8::String>();
   26481          10 :   CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
   26482             : 
   26483             :   // Functions defined in extras do not show up in the stack trace.
   26484          15 :   auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
   26485           5 :                      .ToLocalChecked()
   26486             :                      .As<v8::Function>();
   26487          25 :   CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
   26488             :   ExpectString(
   26489             :       "function f(x) { return wrapper(x) }"
   26490             :       "function g() { return new Error().stack; }"
   26491             :       "f(g)",
   26492             :       "Error\n"
   26493             :       "    at g (<anonymous>:1:58)\n"
   26494             :       "    at f (<anonymous>:1:24)\n"
   26495          10 :       "    at <anonymous>:1:78");
   26496           5 : }
   26497             : 
   26498       28342 : TEST(ExtrasBindingObject) {
   26499           5 :   v8::Isolate* isolate = CcTest::isolate();
   26500           5 :   v8::HandleScope handle_scope(isolate);
   26501          10 :   LocalContext env;
   26502             : 
   26503             :   // standalone.gypi ensures we include the test-extra.js file, which should
   26504             :   // export the tested functions.
   26505           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26506             : 
   26507          15 :   auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
   26508           5 :                   .ToLocalChecked()
   26509             :                   .As<v8::Function>();
   26510             :   auto undefined = v8::Undefined(isolate);
   26511          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   26512           5 :                     .ToLocalChecked()
   26513             :                     .As<v8::Number>();
   26514          10 :   CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
   26515             : 
   26516             :   v8::Local<v8::FunctionTemplate> runtimeFunction =
   26517           5 :       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   26518             :   binding->Set(env.local(), v8_str("runtime"),
   26519          25 :                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   26520          10 :       .FromJust();
   26521          15 :   func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
   26522           5 :              .ToLocalChecked()
   26523             :              .As<v8::Function>();
   26524          10 :   result = func->Call(env.local(), undefined, 0, {})
   26525           5 :                .ToLocalChecked()
   26526             :                .As<v8::Number>();
   26527          15 :   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   26528           5 : }
   26529             : 
   26530             : 
   26531       28342 : TEST(ExtrasCreatePromise) {
   26532           5 :   i::FLAG_allow_natives_syntax = true;
   26533           5 :   LocalContext context;
   26534           5 :   v8::Isolate* isolate = context->GetIsolate();
   26535          10 :   v8::HandleScope handle_scope(isolate);
   26536             : 
   26537          10 :   LocalContext env;
   26538           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26539             : 
   26540          15 :   auto func = binding->Get(env.local(), v8_str("testCreatePromise"))
   26541           5 :                   .ToLocalChecked()
   26542             :                   .As<v8::Function>();
   26543          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26544             : 
   26545             :   auto promise = CompileRun(
   26546             :                      "func();\n"
   26547             :                      "func();\n"
   26548             :                      "%OptimizeFunctionOnNextCall(func);\n"
   26549             :                      "func()\n")
   26550             :                      .As<v8::Promise>();
   26551          10 :   CHECK_EQ(v8::Promise::kPending, promise->State());
   26552           5 : }
   26553             : 
   26554       28342 : TEST(ExtrasCreatePromiseWithParent) {
   26555           5 :   i::FLAG_allow_natives_syntax = true;
   26556           5 :   LocalContext context;
   26557           5 :   v8::Isolate* isolate = context->GetIsolate();
   26558          10 :   v8::HandleScope handle_scope(isolate);
   26559             : 
   26560          10 :   LocalContext env;
   26561           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26562             : 
   26563          15 :   auto func = binding->Get(env.local(), v8_str("testCreatePromiseWithParent"))
   26564           5 :                   .ToLocalChecked()
   26565             :                   .As<v8::Function>();
   26566          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26567             : 
   26568             :   auto promise = CompileRun(
   26569             :                      "var parent = new Promise((a, b) => {});\n"
   26570             :                      "func(parent);\n"
   26571             :                      "func(parent);\n"
   26572             :                      "%OptimizeFunctionOnNextCall(func);\n"
   26573             :                      "func(parent)\n")
   26574             :                      .As<v8::Promise>();
   26575          10 :   CHECK_EQ(v8::Promise::kPending, promise->State());
   26576           5 : }
   26577             : 
   26578       28342 : TEST(ExtrasRejectPromise) {
   26579           5 :   i::FLAG_allow_natives_syntax = true;
   26580           5 :   LocalContext context;
   26581           5 :   v8::Isolate* isolate = context->GetIsolate();
   26582          10 :   v8::HandleScope handle_scope(isolate);
   26583             : 
   26584          10 :   LocalContext env;
   26585           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26586             : 
   26587          15 :   auto func = binding->Get(env.local(), v8_str("testRejectPromise"))
   26588           5 :                   .ToLocalChecked()
   26589             :                   .As<v8::Function>();
   26590          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26591             : 
   26592             :   auto rejected_promise = CompileRun(
   26593             :                               "function newPromise() {\n"
   26594             :                               "  return new Promise((a, b) => {});\n"
   26595             :                               "}\n"
   26596             :                               "func(newPromise(), 1);\n"
   26597             :                               "func(newPromise(), 1);\n"
   26598             :                               "%OptimizeFunctionOnNextCall(func);\n"
   26599             :                               "var promise = newPromise();\n"
   26600             :                               "func(promise, 1);\n"
   26601             :                               "promise;\n")
   26602             :                               .As<v8::Promise>();
   26603           5 :   CHECK_EQ(v8::Promise::kRejected, rejected_promise->State());
   26604          20 :   CHECK_EQ(1, rejected_promise->Result()->Int32Value(env.local()).FromJust());
   26605           5 : }
   26606             : 
   26607       28342 : TEST(ExtrasResolvePromise) {
   26608           5 :   i::FLAG_allow_natives_syntax = true;
   26609           5 :   LocalContext context;
   26610           5 :   v8::Isolate* isolate = context->GetIsolate();
   26611          10 :   v8::HandleScope handle_scope(isolate);
   26612             : 
   26613          10 :   LocalContext env;
   26614           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26615             : 
   26616          15 :   auto func = binding->Get(env.local(), v8_str("testResolvePromise"))
   26617           5 :                   .ToLocalChecked()
   26618             :                   .As<v8::Function>();
   26619          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26620             : 
   26621             :   auto pending_promise = CompileRun(
   26622             :                              "function newPromise() {\n"
   26623             :                              "  return new Promise((a, b) => {});\n"
   26624             :                              "}\n"
   26625             :                              "func(newPromise(), newPromise());\n"
   26626             :                              "func(newPromise(), newPromise());\n"
   26627             :                              "%OptimizeFunctionOnNextCall(func);\n"
   26628             :                              "var promise = newPromise();\n"
   26629             :                              "func(promise, newPromise());\n"
   26630             :                              "promise;\n")
   26631             :                              .As<v8::Promise>();
   26632           5 :   CHECK_EQ(v8::Promise::kPending, pending_promise->State());
   26633             : 
   26634             :   auto fulfilled_promise = CompileRun(
   26635             :                                "function newPromise() {\n"
   26636             :                                "  return new Promise((a, b) => {});\n"
   26637             :                                "}\n"
   26638             :                                "func(newPromise(), 1);\n"
   26639             :                                "func(newPromise(), 1);\n"
   26640             :                                "%OptimizeFunctionOnNextCall(func);\n"
   26641             :                                "var promise = newPromise();\n"
   26642             :                                "func(promise, 1);\n"
   26643             :                                "promise;\n")
   26644             :                                .As<v8::Promise>();
   26645           5 :   CHECK_EQ(v8::Promise::kFulfilled, fulfilled_promise->State());
   26646          20 :   CHECK_EQ(1, fulfilled_promise->Result()->Int32Value(env.local()).FromJust());
   26647           5 : }
   26648             : 
   26649       28342 : TEST(ExtrasUtilsObject) {
   26650           5 :   LocalContext context;
   26651           5 :   v8::Isolate* isolate = context->GetIsolate();
   26652          10 :   v8::HandleScope handle_scope(isolate);
   26653             : 
   26654          10 :   LocalContext env;
   26655           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   26656             : 
   26657          15 :   auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
   26658           5 :                   .ToLocalChecked()
   26659             :                   .As<v8::Function>();
   26660             :   auto undefined = v8::Undefined(isolate);
   26661          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   26662           5 :                     .ToLocalChecked()
   26663             :                     .As<v8::Object>();
   26664             : 
   26665          15 :   auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
   26666           5 :                             .ToLocalChecked()
   26667             :                             .As<v8::Symbol>();
   26668             :   i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
   26669           5 :   CHECK(ips->IsPrivate());
   26670             : 
   26671             :   CompileRun("var result = 0; function store(x) { result = x; }");
   26672           5 :   auto store = CompileRun("store").As<v8::Function>();
   26673             : 
   26674          15 :   auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
   26675           5 :                                .ToLocalChecked()
   26676             :                                .As<v8::Promise>();
   26677           5 :   fulfilled_promise->Then(env.local(), store).ToLocalChecked();
   26678           5 :   isolate->RunMicrotasks();
   26679          15 :   CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
   26680             : 
   26681             :   auto fulfilled_promise_2 =
   26682          15 :       result->Get(env.local(), v8_str("fulfilledPromise2"))
   26683           5 :           .ToLocalChecked()
   26684             :           .As<v8::Promise>();
   26685           5 :   fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
   26686           5 :   isolate->RunMicrotasks();
   26687          15 :   CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
   26688             : 
   26689          15 :   auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
   26690           5 :                               .ToLocalChecked()
   26691             :                               .As<v8::Promise>();
   26692           5 :   rejected_promise->Catch(env.local(), store).ToLocalChecked();
   26693           5 :   isolate->RunMicrotasks();
   26694          15 :   CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
   26695             : 
   26696             :   auto rejected_but_handled_promise =
   26697          15 :       result->Get(env.local(), v8_str("rejectedButHandledPromise"))
   26698           5 :           .ToLocalChecked()
   26699             :           .As<v8::Promise>();
   26700           5 :   CHECK(rejected_but_handled_promise->HasHandler());
   26701             : 
   26702          15 :   auto promise_states = result->Get(env.local(), v8_str("promiseStates"))
   26703           5 :                             .ToLocalChecked()
   26704             :                             .As<v8::String>();
   26705          10 :   String::Utf8Value promise_states_string(isolate, promise_states);
   26706           5 :   CHECK_EQ(0, strcmp(*promise_states_string, "pending fulfilled rejected"));
   26707             : 
   26708          15 :   auto promise_is_promise = result->Get(env.local(), v8_str("promiseIsPromise"))
   26709           5 :                                 .ToLocalChecked()
   26710             :                                 .As<v8::Boolean>();
   26711           5 :   CHECK_EQ(true, promise_is_promise->Value());
   26712             : 
   26713             :   auto thenable_is_promise =
   26714          15 :       result->Get(env.local(), v8_str("thenableIsPromise"))
   26715           5 :           .ToLocalChecked()
   26716             :           .As<v8::Boolean>();
   26717          10 :   CHECK_EQ(false, thenable_is_promise->Value());
   26718             : 
   26719          15 :   auto uncurry_this = result->Get(env.local(), v8_str("uncurryThis"))
   26720           5 :                           .ToLocalChecked()
   26721             :                           .As<v8::Boolean>();
   26722          10 :   CHECK_EQ(true, uncurry_this->Value());
   26723           5 : }
   26724             : 
   26725             : 
   26726       28342 : TEST(Map) {
   26727           5 :   v8::Isolate* isolate = CcTest::isolate();
   26728           5 :   v8::HandleScope handle_scope(isolate);
   26729          10 :   LocalContext env;
   26730             : 
   26731           5 :   v8::Local<v8::Map> map = v8::Map::New(isolate);
   26732           5 :   CHECK(map->IsObject());
   26733           5 :   CHECK(map->IsMap());
   26734          10 :   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
   26735           5 :   CHECK_EQ(0U, map->Size());
   26736             : 
   26737             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
   26738           5 :   CHECK(val->IsMap());
   26739             :   map = v8::Local<v8::Map>::Cast(val);
   26740           5 :   CHECK_EQ(2U, map->Size());
   26741             : 
   26742           5 :   v8::Local<v8::Array> contents = map->AsArray();
   26743           5 :   CHECK_EQ(4U, contents->Length());
   26744          10 :   CHECK_EQ(
   26745             :       1,
   26746             :       contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26747          10 :   CHECK_EQ(
   26748             :       2,
   26749             :       contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26750          10 :   CHECK_EQ(
   26751             :       3,
   26752             :       contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
   26753          10 :   CHECK_EQ(
   26754             :       4,
   26755             :       contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
   26756             : 
   26757           5 :   CHECK_EQ(2U, map->Size());
   26758             : 
   26759          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26760          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26761             : 
   26762          15 :   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26763          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26764             : 
   26765          20 :   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
   26766             :                   .ToLocalChecked()
   26767             :                   ->Int32Value(env.local())
   26768             :                   .FromJust());
   26769          20 :   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
   26770             :                   .ToLocalChecked()
   26771             :                   ->Int32Value(env.local())
   26772             :                   .FromJust());
   26773             : 
   26774          15 :   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
   26775             :             .ToLocalChecked()
   26776             :             ->IsUndefined());
   26777             : 
   26778          10 :   CHECK(!map->Set(env.local(), map, map).IsEmpty());
   26779           5 :   CHECK_EQ(3U, map->Size());
   26780          10 :   CHECK(map->Has(env.local(), map).FromJust());
   26781             : 
   26782          10 :   CHECK(map->Delete(env.local(), map).FromJust());
   26783           5 :   CHECK_EQ(2U, map->Size());
   26784          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26785          10 :   CHECK(!map->Delete(env.local(), map).FromJust());
   26786             : 
   26787           5 :   map->Clear();
   26788          10 :   CHECK_EQ(0U, map->Size());
   26789           5 : }
   26790             : 
   26791             : 
   26792       28342 : TEST(Set) {
   26793           5 :   v8::Isolate* isolate = CcTest::isolate();
   26794           5 :   v8::HandleScope handle_scope(isolate);
   26795          10 :   LocalContext env;
   26796             : 
   26797           5 :   v8::Local<v8::Set> set = v8::Set::New(isolate);
   26798           5 :   CHECK(set->IsObject());
   26799           5 :   CHECK(set->IsSet());
   26800          10 :   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
   26801           5 :   CHECK_EQ(0U, set->Size());
   26802             : 
   26803             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
   26804           5 :   CHECK(val->IsSet());
   26805             :   set = v8::Local<v8::Set>::Cast(val);
   26806           5 :   CHECK_EQ(2U, set->Size());
   26807             : 
   26808           5 :   v8::Local<v8::Array> keys = set->AsArray();
   26809           5 :   CHECK_EQ(2U, keys->Length());
   26810          10 :   CHECK_EQ(1,
   26811             :            keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26812          10 :   CHECK_EQ(2,
   26813             :            keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26814             : 
   26815           5 :   CHECK_EQ(2U, set->Size());
   26816             : 
   26817          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26818          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26819             : 
   26820          15 :   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26821          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26822             : 
   26823          10 :   CHECK(!set->Add(env.local(), set).IsEmpty());
   26824           5 :   CHECK_EQ(3U, set->Size());
   26825          10 :   CHECK(set->Has(env.local(), set).FromJust());
   26826             : 
   26827          10 :   CHECK(set->Delete(env.local(), set).FromJust());
   26828           5 :   CHECK_EQ(2U, set->Size());
   26829          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26830          10 :   CHECK(!set->Delete(env.local(), set).FromJust());
   26831             : 
   26832           5 :   set->Clear();
   26833          10 :   CHECK_EQ(0U, set->Size());
   26834           5 : }
   26835             : 
   26836       28342 : TEST(SetDeleteThenAsArray) {
   26837             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26838           5 :   v8::Isolate* isolate = CcTest::isolate();
   26839           5 :   v8::HandleScope handle_scope(isolate);
   26840          10 :   LocalContext env;
   26841             : 
   26842             :   // make a Set
   26843             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
   26844             :   v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
   26845           5 :   CHECK_EQ(3U, set->Size());
   26846             : 
   26847             :   // delete the "middle" element (using AsArray to
   26848             :   // determine which element is the "middle" element)
   26849           5 :   v8::Local<v8::Array> array1 = set->AsArray();
   26850           5 :   CHECK_EQ(3U, array1->Length());
   26851          15 :   CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
   26852             :             .FromJust());
   26853             : 
   26854             :   // make sure there are no undefined values when we convert to an array again.
   26855           5 :   v8::Local<v8::Array> array2 = set->AsArray();
   26856           5 :   uint32_t length = array2->Length();
   26857           5 :   CHECK_EQ(2U, length);
   26858          10 :   for (uint32_t i = 0; i < length; i++) {
   26859          20 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26860           5 :   }
   26861           5 : }
   26862             : 
   26863       28342 : TEST(MapDeleteThenAsArray) {
   26864             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26865           5 :   v8::Isolate* isolate = CcTest::isolate();
   26866           5 :   v8::HandleScope handle_scope(isolate);
   26867          10 :   LocalContext env;
   26868             : 
   26869             :   // make a Map
   26870             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
   26871             :   v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
   26872           5 :   CHECK_EQ(3U, map->Size());
   26873             : 
   26874             :   // delete the "middle" element (using AsArray to
   26875             :   // determine which element is the "middle" element)
   26876           5 :   v8::Local<v8::Array> array1 = map->AsArray();
   26877           5 :   CHECK_EQ(6U, array1->Length());
   26878             :   // Map::AsArray returns a flat array, so the second key is at index 2.
   26879          10 :   v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
   26880          10 :   CHECK(map->Delete(env.local(), key).FromJust());
   26881             : 
   26882             :   // make sure there are no undefined values when we convert to an array again.
   26883           5 :   v8::Local<v8::Array> array2 = map->AsArray();
   26884           5 :   uint32_t length = array2->Length();
   26885           5 :   CHECK_EQ(4U, length);
   26886          20 :   for (uint32_t i = 0; i < length; i++) {
   26887          40 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26888           5 :   }
   26889           5 : }
   26890             : 
   26891       28342 : TEST(CompatibleReceiverCheckOnCachedICHandler) {
   26892           5 :   v8::Isolate* isolate = CcTest::isolate();
   26893           5 :   v8::HandleScope scope(isolate);
   26894           5 :   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
   26895           5 :   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
   26896             :   auto returns_42 =
   26897           5 :       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
   26898          15 :   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
   26899           5 :   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
   26900           5 :   child->Inherit(parent);
   26901          10 :   LocalContext env;
   26902          30 :   CHECK(env->Global()
   26903             :             ->Set(env.local(), v8_str("Child"),
   26904             :                   child->GetFunction(env.local()).ToLocalChecked())
   26905             :             .FromJust());
   26906             : 
   26907             :   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
   26908             :   CompileRun(
   26909             :       "var real = new Child();\n"
   26910             :       "for (var i = 0; i < 3; ++i) {\n"
   26911             :       "  real.age;\n"
   26912             :       "}\n");
   26913             : 
   26914             :   // Check that the cached stub is never used.
   26915             :   ExpectInt32(
   26916             :       "var fake = Object.create(Child.prototype);\n"
   26917             :       "var result = 0;\n"
   26918             :       "function test(d) {\n"
   26919             :       "  if (d == 3) return;\n"
   26920             :       "  try {\n"
   26921             :       "    fake.age;\n"
   26922             :       "    result = 1;\n"
   26923             :       "  } catch (e) {\n"
   26924             :       "  }\n"
   26925             :       "  test(d+1);\n"
   26926             :       "}\n"
   26927             :       "test(0);\n"
   26928             :       "result;\n",
   26929          10 :       0);
   26930           5 : }
   26931             : 
   26932       28343 : THREADED_TEST(ReceiverConversionForAccessors) {
   26933           6 :   LocalContext env;
   26934           6 :   v8::Isolate* isolate = CcTest::isolate();
   26935          12 :   v8::HandleScope scope(isolate);
   26936             :   Local<v8::FunctionTemplate> acc =
   26937           6 :       v8::FunctionTemplate::New(isolate, Returns42);
   26938          42 :   CHECK(env->Global()
   26939             :             ->Set(env.local(), v8_str("acc"),
   26940             :                   acc->GetFunction(env.local()).ToLocalChecked())
   26941             :             .FromJust());
   26942             : 
   26943           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   26944          12 :   templ->SetAccessorProperty(v8_str("acc"), acc, acc);
   26945           6 :   Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   26946             : 
   26947          30 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
   26948           6 :   CHECK(CompileRun("(p.acc == 42)")->BooleanValue(isolate));
   26949           6 :   CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(isolate));
   26950             : 
   26951           6 :   CHECK(!CompileRun("Number.prototype.__proto__ = p;"
   26952             :                     "var a = 1;")
   26953             :              .IsEmpty());
   26954           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26955           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26956             : 
   26957           6 :   CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
   26958             :                     "var a = true;")
   26959             :              .IsEmpty());
   26960           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26961           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26962             : 
   26963           6 :   CHECK(!CompileRun("String.prototype.__proto__ = p;"
   26964             :                     "var a = 'foo';")
   26965             :              .IsEmpty());
   26966           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26967           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26968             : 
   26969           6 :   CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(isolate));
   26970           6 :   CHECK(CompileRun("acc.call(true)==42")->BooleanValue(isolate));
   26971           6 :   CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(isolate));
   26972           6 :   CHECK(CompileRun("acc.call(null) == 42")->BooleanValue(isolate));
   26973          12 :   CHECK(CompileRun("acc.call(undefined) == 42")->BooleanValue(isolate));
   26974           6 : }
   26975             : 
   26976           5 : class FutexInterruptionThread : public v8::base::Thread {
   26977             :  public:
   26978             :   explicit FutexInterruptionThread(v8::Isolate* isolate)
   26979           5 :       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
   26980             : 
   26981           5 :   void Run() override {
   26982             :     // Wait a bit before terminating.
   26983           5 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   26984           5 :     isolate_->TerminateExecution();
   26985           5 :   }
   26986             : 
   26987             :  private:
   26988             :   v8::Isolate* isolate_;
   26989             : };
   26990             : 
   26991             : 
   26992       28342 : TEST(FutexInterruption) {
   26993           5 :   i::FLAG_harmony_sharedarraybuffer = true;
   26994           5 :   v8::Isolate* isolate = CcTest::isolate();
   26995           5 :   v8::HandleScope scope(isolate);
   26996          10 :   LocalContext env;
   26997             : 
   26998             :   FutexInterruptionThread timeout_thread(isolate);
   26999             : 
   27000          10 :   v8::TryCatch try_catch(CcTest::isolate());
   27001           5 :   timeout_thread.Start();
   27002             : 
   27003             :   CompileRun(
   27004             :       "var ab = new SharedArrayBuffer(4);"
   27005             :       "var i32a = new Int32Array(ab);"
   27006             :       "Atomics.wait(i32a, 0, 0);");
   27007           5 :   CHECK(try_catch.HasTerminated());
   27008          10 :   timeout_thread.Join();
   27009           5 : }
   27010             : 
   27011       28343 : THREADED_TEST(SharedArrayBuffer_AllocationInformation) {
   27012           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   27013           6 :   LocalContext env;
   27014           6 :   v8::Isolate* isolate = env->GetIsolate();
   27015          12 :   v8::HandleScope handle_scope(isolate);
   27016             : 
   27017             :   const size_t ab_size = 1024;
   27018             :   Local<v8::SharedArrayBuffer> ab =
   27019           6 :       v8::SharedArrayBuffer::New(isolate, ab_size);
   27020          12 :   ScopedSharedArrayBufferContents contents(ab->Externalize());
   27021             : 
   27022             :   // Array buffers should have normal allocation mode.
   27023           6 :   CHECK_EQ(contents.AllocationMode(),
   27024             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
   27025             :   // The allocation must contain the buffer (normally they will be equal, but
   27026             :   // this is not required by the contract).
   27027           6 :   CHECK_NOT_NULL(contents.AllocationBase());
   27028             :   const uintptr_t alloc =
   27029           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
   27030           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
   27031           6 :   CHECK_LE(alloc, data);
   27032          12 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
   27033           6 : }
   27034             : 
   27035             : static int nb_uncaught_exception_callback_calls = 0;
   27036             : 
   27037             : 
   27038           5 : bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
   27039           5 :   ++nb_uncaught_exception_callback_calls;
   27040           5 :   return false;
   27041             : }
   27042             : 
   27043             : 
   27044       28342 : TEST(AbortOnUncaughtExceptionNoAbort) {
   27045           5 :   v8::Isolate* isolate = CcTest::isolate();
   27046           5 :   v8::HandleScope handle_scope(isolate);
   27047             :   v8::Local<v8::ObjectTemplate> global_template =
   27048           5 :       v8::ObjectTemplate::New(isolate);
   27049          10 :   LocalContext env(nullptr, global_template);
   27050             : 
   27051           5 :   i::FLAG_abort_on_uncaught_exception = true;
   27052           5 :   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
   27053             : 
   27054             :   CompileRun("function boom() { throw new Error(\"boom\") }");
   27055             : 
   27056           5 :   v8::Local<v8::Object> global_object = env->Global();
   27057             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   27058          20 :       global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
   27059             : 
   27060          10 :   CHECK(foo->Call(env.local(), global_object, 0, nullptr).IsEmpty());
   27061             : 
   27062          10 :   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
   27063           5 : }
   27064             : 
   27065             : 
   27066       28342 : TEST(AccessCheckedIsConcatSpreadable) {
   27067           5 :   v8::Isolate* isolate = CcTest::isolate();
   27068           5 :   HandleScope scope(isolate);
   27069          10 :   LocalContext env;
   27070             : 
   27071             :   // Object with access check
   27072           5 :   Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
   27073           5 :   spreadable_template->SetAccessCheckCallback(AccessBlocker);
   27074             :   spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
   27075          10 :                            v8::Boolean::New(isolate, true));
   27076             :   Local<Object> object =
   27077           5 :       spreadable_template->NewInstance(env.local()).ToLocalChecked();
   27078             : 
   27079           5 :   allowed_access = true;
   27080          25 :   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   27081          15 :   object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
   27082          15 :   object->Set(env.local(), 0U, v8_str("a")).FromJust();
   27083          15 :   object->Set(env.local(), 1U, v8_str("b")).FromJust();
   27084             : 
   27085             :   // Access check is allowed, and the object is spread
   27086             :   CompileRun("var result = [].concat(object)");
   27087             :   ExpectTrue("Array.isArray(result)");
   27088           5 :   ExpectString("result[0]", "a");
   27089           5 :   ExpectString("result[1]", "b");
   27090             :   ExpectTrue("result.length === 2");
   27091             :   ExpectTrue("object[Symbol.isConcatSpreadable]");
   27092             : 
   27093             :   // If access check fails, the value of @@isConcatSpreadable is ignored
   27094           5 :   allowed_access = false;
   27095             :   CompileRun("var result = [].concat(object)");
   27096             :   ExpectTrue("Array.isArray(result)");
   27097             :   ExpectTrue("result[0] === object");
   27098             :   ExpectTrue("result.length === 1");
   27099           5 :   ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
   27100           5 : }
   27101             : 
   27102             : 
   27103       28342 : TEST(AccessCheckedToStringTag) {
   27104           5 :   v8::Isolate* isolate = CcTest::isolate();
   27105           5 :   HandleScope scope(isolate);
   27106          10 :   LocalContext env;
   27107             : 
   27108             :   // Object with access check
   27109           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   27110           5 :   object_template->SetAccessCheckCallback(AccessBlocker);
   27111             :   Local<Object> object =
   27112           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   27113             : 
   27114           5 :   allowed_access = true;
   27115          25 :   env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
   27116          20 :   object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
   27117          10 :       .FromJust();
   27118             : 
   27119             :   // Access check is allowed, and the toStringTag is read
   27120             :   CompileRun("var result = Object.prototype.toString.call(object)");
   27121           5 :   ExpectString("result", "[object hello]");
   27122           5 :   ExpectString("object[Symbol.toStringTag]", "hello");
   27123             : 
   27124             :   // ToString through the API should succeed too.
   27125             :   String::Utf8Value result_allowed(
   27126          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   27127           5 :   CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
   27128             : 
   27129             :   // If access check fails, the value of @@toStringTag is ignored
   27130           5 :   allowed_access = false;
   27131             :   CompileRun("var result = Object.prototype.toString.call(object)");
   27132           5 :   ExpectString("result", "[object Object]");
   27133             :   ExpectTrue("object[Symbol.toStringTag] === undefined");
   27134             : 
   27135             :   // ToString through the API should also fail.
   27136             :   String::Utf8Value result_denied(
   27137          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   27138          10 :   CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
   27139           5 : }
   27140             : 
   27141       28342 : TEST(TemplateIteratorPrototypeIntrinsics) {
   27142           5 :   v8::Isolate* isolate = CcTest::isolate();
   27143           5 :   v8::HandleScope scope(isolate);
   27144          10 :   LocalContext env;
   27145             : 
   27146             :   // Object templates.
   27147             :   {
   27148           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   27149             :     object_template->SetIntrinsicDataProperty(v8_str("iter_proto"),
   27150          10 :                                               v8::kIteratorPrototype);
   27151             :     Local<Object> object =
   27152           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   27153          25 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   27154             :     ExpectTrue("obj.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   27155             :   }
   27156             :   // Setting %IteratorProto% on the function object's prototype template.
   27157             :   {
   27158           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   27159          10 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   27160          15 :         v8_str("iter_proto"), v8::kIteratorPrototype);
   27161             :     Local<Function> func1 =
   27162           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   27163          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   27164             :     Local<Function> func2 =
   27165           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   27166          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   27167             :     ExpectTrue(
   27168             :         "func1.prototype.iter_proto === "
   27169             :         "[][Symbol.iterator]().__proto__.__proto__");
   27170             :     ExpectTrue(
   27171             :         "func2.prototype.iter_proto === "
   27172             :         "[][Symbol.iterator]().__proto__.__proto__");
   27173             :     ExpectTrue("func1.prototype.iter_proto === func2.prototype.iter_proto");
   27174             : 
   27175           5 :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   27176          25 :     CHECK(env->Global()
   27177             :               ->Set(env.local(), v8_str("instance1"), instance1)
   27178             :               .FromJust());
   27179             :     ExpectFalse("instance1.hasOwnProperty('iter_proto')");
   27180             :     ExpectTrue("'iter_proto' in instance1.__proto__");
   27181             :     ExpectTrue(
   27182             :         "instance1.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   27183             :   }
   27184             :   // Put %IteratorProto% in a function object's inheritance chain.
   27185             :   {
   27186             :     Local<FunctionTemplate> parent_template =
   27187           5 :         v8::FunctionTemplate::New(isolate);
   27188           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   27189             :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   27190          10 :                                               v8::kIteratorPrototype);
   27191           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   27192           5 :     func_template->Inherit(parent_template);
   27193             : 
   27194             :     Local<Function> func =
   27195           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   27196          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   27197             :     ExpectTrue(
   27198             :         "func.prototype.__proto__ === "
   27199             :         "[][Symbol.iterator]().__proto__.__proto__");
   27200             : 
   27201             :     Local<Object> func_instance =
   27202           5 :         func->NewInstance(env.local()).ToLocalChecked();
   27203          25 :     CHECK(env->Global()
   27204             :               ->Set(env.local(), v8_str("instance"), func_instance)
   27205             :               .FromJust());
   27206             :     ExpectTrue(
   27207             :         "instance.__proto__.__proto__ === "
   27208             :         "[][Symbol.iterator]().__proto__.__proto__");
   27209             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   27210           5 :   }
   27211           5 : }
   27212             : 
   27213       28342 : TEST(TemplateErrorPrototypeIntrinsics) {
   27214           5 :   v8::Isolate* isolate = CcTest::isolate();
   27215           5 :   v8::HandleScope scope(isolate);
   27216          10 :   LocalContext env;
   27217             : 
   27218             :   // Object templates.
   27219             :   {
   27220           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   27221             :     object_template->SetIntrinsicDataProperty(v8_str("error_proto"),
   27222          10 :                                               v8::kErrorPrototype);
   27223             :     Local<Object> object =
   27224           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   27225          25 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   27226             :     ExpectTrue("obj.error_proto === Error.prototype");
   27227           5 :     Local<Value> error = v8::Exception::Error(v8_str("error message"));
   27228          25 :     CHECK(env->Global()->Set(env.local(), v8_str("err"), error).FromJust());
   27229             :     ExpectTrue("obj.error_proto === Object.getPrototypeOf(err)");
   27230             :   }
   27231             :   // Setting %ErrorPrototype% on the function object's prototype template.
   27232             :   {
   27233           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   27234          10 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   27235          15 :         v8_str("error_proto"), v8::kErrorPrototype);
   27236             :     Local<Function> func1 =
   27237           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   27238          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   27239             :     Local<Function> func2 =
   27240           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   27241          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   27242             :     ExpectTrue("func1.prototype.error_proto === Error.prototype");
   27243             :     ExpectTrue("func2.prototype.error_proto === Error.prototype");
   27244             :     ExpectTrue("func1.prototype.error_proto === func2.prototype.error_proto");
   27245             : 
   27246           5 :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   27247          25 :     CHECK(env->Global()
   27248             :               ->Set(env.local(), v8_str("instance1"), instance1)
   27249             :               .FromJust());
   27250             :     ExpectFalse("instance1.hasOwnProperty('error_proto')");
   27251             :     ExpectTrue("'error_proto' in instance1.__proto__");
   27252             :     ExpectTrue("instance1.error_proto === Error.prototype");
   27253             :   }
   27254             :   // Put %ErrorPrototype% in a function object's inheritance chain.
   27255             :   {
   27256             :     Local<FunctionTemplate> parent_template =
   27257           5 :         v8::FunctionTemplate::New(isolate);
   27258           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   27259             :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   27260          10 :                                               v8::kErrorPrototype);
   27261           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   27262           5 :     func_template->Inherit(parent_template);
   27263             : 
   27264             :     Local<Function> func =
   27265           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   27266          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   27267             :     ExpectTrue("func.prototype.__proto__ === Error.prototype");
   27268             : 
   27269             :     Local<Object> func_instance =
   27270           5 :         func->NewInstance(env.local()).ToLocalChecked();
   27271          25 :     CHECK(env->Global()
   27272             :               ->Set(env.local(), v8_str("instance"), func_instance)
   27273             :               .FromJust());
   27274             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   27275             :     // Now let's check if %ErrorPrototype% properties are in the instance.
   27276             :     ExpectTrue("'constructor' in instance");
   27277             :     ExpectTrue("'message' in instance");
   27278             :     ExpectTrue("'name' in instance");
   27279             :     ExpectTrue("'toString' in instance");
   27280           5 :   }
   27281           5 : }
   27282             : 
   27283       28342 : TEST(ObjectTemplateArrayProtoIntrinsics) {
   27284           5 :   v8::Isolate* isolate = CcTest::isolate();
   27285           5 :   v8::HandleScope scope(isolate);
   27286          10 :   LocalContext env;
   27287             : 
   27288           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   27289             :   object_template->SetIntrinsicDataProperty(v8_str("prop_entries"),
   27290          10 :                                             v8::kArrayProto_entries);
   27291             :   object_template->SetIntrinsicDataProperty(v8_str("prop_forEach"),
   27292          10 :                                             v8::kArrayProto_forEach);
   27293             :   object_template->SetIntrinsicDataProperty(v8_str("prop_keys"),
   27294          10 :                                             v8::kArrayProto_keys);
   27295             :   object_template->SetIntrinsicDataProperty(v8_str("prop_values"),
   27296          10 :                                             v8::kArrayProto_values);
   27297             :   Local<Object> object =
   27298           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   27299          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   27300             : 
   27301             :   const struct {
   27302             :     const char* const object_property_name;
   27303             :     const char* const array_property_name;
   27304             :   } intrinsics_comparisons[] = {
   27305             :       {"prop_entries", "Array.prototype.entries"},
   27306             :       {"prop_forEach", "Array.prototype.forEach"},
   27307             :       {"prop_keys", "Array.prototype.keys"},
   27308             :       {"prop_values", "Array.prototype[Symbol.iterator]"},
   27309           5 :   };
   27310             : 
   27311          25 :   for (unsigned i = 0; i < arraysize(intrinsics_comparisons); i++) {
   27312             :     i::ScopedVector<char> test_string(64);
   27313             : 
   27314             :     i::SNPrintF(test_string, "typeof obj1.%s",
   27315          20 :                 intrinsics_comparisons[i].object_property_name);
   27316          20 :     ExpectString(test_string.start(), "function");
   27317             : 
   27318             :     i::SNPrintF(test_string, "obj1.%s === %s",
   27319             :                 intrinsics_comparisons[i].object_property_name,
   27320          20 :                 intrinsics_comparisons[i].array_property_name);
   27321             :     ExpectTrue(test_string.start());
   27322             : 
   27323             :     i::SNPrintF(test_string, "obj1.%s = 42",
   27324          20 :                 intrinsics_comparisons[i].object_property_name);
   27325             :     CompileRun(test_string.start());
   27326             : 
   27327             :     i::SNPrintF(test_string, "obj1.%s === %s",
   27328             :                 intrinsics_comparisons[i].object_property_name,
   27329          20 :                 intrinsics_comparisons[i].array_property_name);
   27330             :     ExpectFalse(test_string.start());
   27331             : 
   27332             :     i::SNPrintF(test_string, "typeof obj1.%s",
   27333          20 :                 intrinsics_comparisons[i].object_property_name);
   27334          20 :     ExpectString(test_string.start(), "number");
   27335           5 :   }
   27336           5 : }
   27337             : 
   27338       28342 : TEST(ObjectTemplatePerContextIntrinsics) {
   27339           5 :   v8::Isolate* isolate = CcTest::isolate();
   27340           5 :   v8::HandleScope scope(isolate);
   27341          10 :   LocalContext env;
   27342             : 
   27343           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   27344             :   object_template->SetIntrinsicDataProperty(v8_str("values"),
   27345          10 :                                             v8::kArrayProto_values);
   27346             :   Local<Object> object =
   27347           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   27348             : 
   27349          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   27350           5 :   ExpectString("typeof obj1.values", "function");
   27351             : 
   27352             :   auto values = Local<Function>::Cast(
   27353          15 :       object->Get(env.local(), v8_str("values")).ToLocalChecked());
   27354           5 :   auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
   27355          10 :   auto ctx = v8::Utils::OpenHandle(*env.local());
   27356          20 :   CHECK_EQ(*fn->GetCreationContext(), *ctx);
   27357             : 
   27358             :   {
   27359           5 :     LocalContext env2;
   27360             :     Local<Object> object2 =
   27361           5 :         object_template->NewInstance(env2.local()).ToLocalChecked();
   27362          25 :     CHECK(
   27363             :         env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
   27364           5 :     ExpectString("typeof obj2.values", "function");
   27365          25 :     CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
   27366             :              *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   27367             : 
   27368             :     auto values2 = Local<Function>::Cast(
   27369          15 :         object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   27370           5 :     auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
   27371          10 :     auto ctx2 = v8::Utils::OpenHandle(*env2.local());
   27372          20 :     CHECK_EQ(*fn2->GetCreationContext(), *ctx2);
   27373           5 :   }
   27374           5 : }
   27375             : 
   27376             : 
   27377       28342 : TEST(Proxy) {
   27378           5 :   LocalContext context;
   27379           5 :   v8::Isolate* isolate = CcTest::isolate();
   27380          10 :   v8::HandleScope scope(isolate);
   27381             :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   27382             :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   27383             : 
   27384             :   v8::Local<v8::Proxy> proxy =
   27385           5 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   27386           5 :   CHECK(proxy->IsProxy());
   27387           5 :   CHECK(!target->IsProxy());
   27388           5 :   CHECK(!proxy->IsRevoked());
   27389          10 :   CHECK(proxy->GetTarget()->SameValue(target));
   27390          10 :   CHECK(proxy->GetHandler()->SameValue(handler));
   27391             : 
   27392           5 :   proxy->Revoke();
   27393           5 :   CHECK(proxy->IsProxy());
   27394           5 :   CHECK(!target->IsProxy());
   27395           5 :   CHECK(proxy->IsRevoked());
   27396          10 :   CHECK(proxy->GetTarget()->IsNull());
   27397          15 :   CHECK(proxy->GetHandler()->IsNull());
   27398           5 : }
   27399             : 
   27400          10 : WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
   27401             :     v8::Isolate* isolate, WeakCallCounter* counter) {
   27402             :   v8::Locker locker(isolate);
   27403          20 :   LocalContext env;
   27404          20 :   HandleScope scope(isolate);
   27405             :   WeakCallCounterAndPersistent<Value>* val =
   27406          10 :       new WeakCallCounterAndPersistent<Value>(counter);
   27407          20 :   val->handle.Reset(isolate, Object::New(isolate));
   27408             :   val->handle.SetWeak(val, &WeakPointerCallback,
   27409             :                       v8::WeakCallbackType::kParameter);
   27410          10 :   return val;
   27411             : }
   27412             : 
   27413           5 : class MemoryPressureThread : public v8::base::Thread {
   27414             :  public:
   27415             :   explicit MemoryPressureThread(v8::Isolate* isolate,
   27416             :                                 v8::MemoryPressureLevel level)
   27417             :       : Thread(Options("MemoryPressureThread")),
   27418             :         isolate_(isolate),
   27419           5 :         level_(level) {}
   27420             : 
   27421           5 :   void Run() override { isolate_->MemoryPressureNotification(level_); }
   27422             : 
   27423             :  private:
   27424             :   v8::Isolate* isolate_;
   27425             :   v8::MemoryPressureLevel level_;
   27426             : };
   27427             : 
   27428       28342 : TEST(MemoryPressure) {
   27429           5 :   if (v8::internal::FLAG_optimize_for_size) return;
   27430           5 :   v8::Isolate* isolate = CcTest::isolate();
   27431             :   WeakCallCounter counter(1234);
   27432             : 
   27433             :   // Check that critical memory pressure notification sets GC interrupt.
   27434           5 :   auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   27435           5 :   CHECK(!v8::Locker::IsLocked(isolate));
   27436             :   {
   27437             :     v8::Locker locker(isolate);
   27438          10 :     v8::HandleScope scope(isolate);
   27439          10 :     LocalContext env;
   27440             :     MemoryPressureThread memory_pressure_thread(
   27441             :         isolate, v8::MemoryPressureLevel::kCritical);
   27442           5 :     memory_pressure_thread.Start();
   27443           5 :     memory_pressure_thread.Join();
   27444             :     // This should trigger GC.
   27445           5 :     CHECK_EQ(0, counter.NumberOfWeakCalls());
   27446             :     CompileRun("(function noop() { return 0; })()");
   27447          10 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   27448             :   }
   27449           5 :   delete garbage;
   27450             :   // Check that critical memory pressure notification triggers GC.
   27451           5 :   garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   27452             :   {
   27453             :     v8::Locker locker(isolate);
   27454             :     // If isolate is locked, memory pressure notification should trigger GC.
   27455           5 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   27456           5 :     isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
   27457           5 :     CHECK_EQ(2, counter.NumberOfWeakCalls());
   27458             :   }
   27459           5 :   delete garbage;
   27460             :   // Check that moderate memory pressure notification sets GC into memory
   27461             :   // optimizing mode.
   27462           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
   27463           5 :   CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   27464             :   // Check that disabling memory pressure returns GC into normal mode.
   27465           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
   27466           5 :   CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   27467             : }
   27468             : 
   27469       28342 : TEST(SetIntegrityLevel) {
   27470           5 :   LocalContext context;
   27471           5 :   v8::Isolate* isolate = CcTest::isolate();
   27472          10 :   v8::HandleScope scope(isolate);
   27473             : 
   27474           5 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   27475          25 :   CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   27476             : 
   27477             :   v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
   27478           5 :   CHECK(!is_frozen->BooleanValue(isolate));
   27479             : 
   27480          10 :   CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
   27481             :             .FromJust());
   27482             : 
   27483             :   is_frozen = CompileRun("Object.isFrozen(o)");
   27484          10 :   CHECK(is_frozen->BooleanValue(isolate));
   27485           5 : }
   27486             : 
   27487       28342 : TEST(PrivateForApiIsNumber) {
   27488           5 :   LocalContext context;
   27489           5 :   v8::Isolate* isolate = CcTest::isolate();
   27490          10 :   v8::HandleScope scope(isolate);
   27491             : 
   27492             :   // Shouldn't crash.
   27493          10 :   v8::Private::ForApi(isolate, v8_str("42"));
   27494           5 : }
   27495             : 
   27496       28343 : THREADED_TEST(ImmutableProto) {
   27497           6 :   LocalContext context;
   27498           6 :   v8::Isolate* isolate = context->GetIsolate();
   27499          12 :   v8::HandleScope handle_scope(isolate);
   27500             : 
   27501           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   27502          12 :   templ->InstanceTemplate()->SetImmutableProto();
   27503             : 
   27504           6 :   Local<v8::Object> object = templ->GetFunction(context.local())
   27505           6 :                                  .ToLocalChecked()
   27506           6 :                                  ->NewInstance(context.local())
   27507             :                                  .ToLocalChecked();
   27508             : 
   27509             :   // Look up the prototype
   27510             :   Local<v8::Value> original_proto =
   27511          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   27512             : 
   27513             :   // Setting the prototype (e.g., to null) throws
   27514          12 :   CHECK(object->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   27515             : 
   27516             :   // The original prototype is still there
   27517             :   Local<Value> new_proto =
   27518          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   27519           6 :   CHECK(new_proto->IsObject());
   27520          12 :   CHECK(new_proto.As<v8::Object>()
   27521             :             ->Equals(context.local(), original_proto)
   27522           6 :             .FromJust());
   27523           6 : }
   27524             : 
   27525             : Local<v8::Context> call_eval_context;
   27526             : Local<v8::Function> call_eval_bound_function;
   27527             : 
   27528          10 : static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
   27529             :   v8::Context::Scope scope(call_eval_context);
   27530             :   args.GetReturnValue().Set(
   27531             :       call_eval_bound_function
   27532          10 :           ->Call(call_eval_context, call_eval_context->Global(), 0, nullptr)
   27533           5 :           .ToLocalChecked());
   27534           5 : }
   27535             : 
   27536       28342 : TEST(CrossActivationEval) {
   27537           5 :   LocalContext env;
   27538           5 :   v8::Isolate* isolate = env->GetIsolate();
   27539          10 :   v8::HandleScope scope(isolate);
   27540             :   {
   27541           5 :     call_eval_context = v8::Context::New(isolate);
   27542             :     v8::Context::Scope scope(call_eval_context);
   27543             :     call_eval_bound_function =
   27544           5 :         Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
   27545             :   }
   27546             :   env->Global()
   27547             :       ->Set(env.local(), v8_str("CallEval"),
   27548           5 :             v8::FunctionTemplate::New(isolate, CallEval)
   27549          15 :                 ->GetFunction(env.local())
   27550          25 :                 .ToLocalChecked())
   27551          10 :       .FromJust();
   27552             :   Local<Value> result = CompileRun("CallEval();");
   27553           5 :   CHECK(result->IsInt32());
   27554          15 :   CHECK_EQ(1, result->Int32Value(env.local()).FromJust());
   27555           5 : }
   27556             : 
   27557       28342 : TEST(EvalInAccessCheckedContext) {
   27558           5 :   v8::Isolate* isolate = CcTest::isolate();
   27559           5 :   v8::HandleScope scope(isolate);
   27560             : 
   27561           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   27562             : 
   27563           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysAllowed);
   27564             : 
   27565           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   27566           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, obj_template);
   27567             : 
   27568           5 :   Local<Value> foo = v8_str("foo");
   27569           5 :   Local<Value> bar = v8_str("bar");
   27570             : 
   27571             :   // Set to different domains.
   27572           5 :   context0->SetSecurityToken(foo);
   27573           5 :   context1->SetSecurityToken(bar);
   27574             : 
   27575             :   // Set up function in context0 that uses eval from context0.
   27576           5 :   context0->Enter();
   27577             :   v8::Local<v8::Value> fun = CompileRun(
   27578             :       "var x = 42;"
   27579             :       "(function() {"
   27580             :       "  var e = eval;"
   27581             :       "  return function(s) { return e(s); }"
   27582           5 :       "})()");
   27583           5 :   context0->Exit();
   27584             : 
   27585             :   // Put the function into context1 and call it. Since the access check
   27586             :   // callback always returns true, the call succeeds even though the tokens
   27587             :   // are different.
   27588           5 :   context1->Enter();
   27589          20 :   context1->Global()->Set(context1, v8_str("fun"), fun).FromJust();
   27590             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   27591          10 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   27592           5 :   context1->Exit();
   27593           5 : }
   27594             : 
   27595       28343 : THREADED_TEST(ImmutableProtoWithParent) {
   27596           6 :   LocalContext context;
   27597           6 :   v8::Isolate* isolate = context->GetIsolate();
   27598          12 :   v8::HandleScope handle_scope(isolate);
   27599             : 
   27600           6 :   Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate);
   27601             : 
   27602           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   27603           6 :   templ->Inherit(parent);
   27604          12 :   templ->PrototypeTemplate()->SetImmutableProto();
   27605             : 
   27606             :   Local<v8::Function> function =
   27607           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   27608             :   Local<v8::Object> instance =
   27609           6 :       function->NewInstance(context.local()).ToLocalChecked();
   27610             :   Local<v8::Object> prototype =
   27611          18 :       instance->Get(context.local(), v8_str("__proto__"))
   27612           6 :           .ToLocalChecked()
   27613           6 :           ->ToObject(context.local())
   27614           6 :           .ToLocalChecked();
   27615             : 
   27616             :   // Look up the prototype
   27617             :   Local<v8::Value> original_proto =
   27618          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   27619             : 
   27620             :   // Setting the prototype (e.g., to null) throws
   27621          12 :   CHECK(
   27622             :       prototype->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   27623             : 
   27624             :   // The original prototype is still there
   27625             :   Local<Value> new_proto =
   27626          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   27627           6 :   CHECK(new_proto->IsObject());
   27628          12 :   CHECK(new_proto.As<v8::Object>()
   27629             :             ->Equals(context.local(), original_proto)
   27630           6 :             .FromJust());
   27631           6 : }
   27632             : 
   27633       28342 : TEST(InternalFieldsOnGlobalProxy) {
   27634           5 :   v8::Isolate* isolate = CcTest::isolate();
   27635           5 :   v8::HandleScope scope(isolate);
   27636             : 
   27637           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   27638           5 :   obj_template->SetInternalFieldCount(1);
   27639             : 
   27640           5 :   v8::Local<v8::Context> context = Context::New(isolate, nullptr, obj_template);
   27641           5 :   v8::Local<v8::Object> global = context->Global();
   27642           5 :   CHECK_EQ(1, global->InternalFieldCount());
   27643           5 : }
   27644             : 
   27645       28343 : THREADED_TEST(ImmutableProtoGlobal) {
   27646           6 :   v8::Isolate* isolate = CcTest::isolate();
   27647           6 :   v8::HandleScope handle_scope(isolate);
   27648           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   27649           6 :   global_template->SetImmutableProto();
   27650           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
   27651             :   Context::Scope context_scope(context);
   27652             :   v8::Local<Value> result = CompileRun(
   27653             :       "global = this;"
   27654             :       "(function() {"
   27655             :       "  try {"
   27656             :       "    global.__proto__ = {};"
   27657             :       "    return 0;"
   27658             :       "  } catch (e) {"
   27659             :       "    return 1;"
   27660             :       "  }"
   27661             :       "})()");
   27662          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 1))
   27663           6 :             .FromJust());
   27664           6 : }
   27665             : 
   27666       28343 : THREADED_TEST(MutableProtoGlobal) {
   27667           6 :   v8::Isolate* isolate = CcTest::isolate();
   27668           6 :   v8::HandleScope handle_scope(isolate);
   27669           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   27670           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
   27671             :   Context::Scope context_scope(context);
   27672             :   v8::Local<Value> result = CompileRun(
   27673             :       "global = this;"
   27674             :       "(function() {"
   27675             :       "  try {"
   27676             :       "    global.__proto__ = {};"
   27677             :       "    return 0;"
   27678             :       "  } catch (e) {"
   27679             :       "    return 1;"
   27680             :       "  }"
   27681             :       "})()");
   27682          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 0))
   27683           6 :             .FromJust());
   27684           6 : }
   27685             : 
   27686       28342 : TEST(InternalFieldsOnTypedArray) {
   27687           5 :   LocalContext env;
   27688           5 :   v8::Isolate* isolate = env->GetIsolate();
   27689          10 :   v8::HandleScope scope(isolate);
   27690           5 :   v8::Local<v8::Context> context = env.local();
   27691             :   Context::Scope context_scope(context);
   27692           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   27693           5 :   v8::Local<v8::Uint8Array> array = v8::Uint8Array::New(buffer, 0, 1);
   27694          15 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   27695          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   27696             :              array->GetAlignedPointerFromInternalField(i));
   27697           5 :   }
   27698           5 : }
   27699             : 
   27700       28342 : TEST(InternalFieldsOnDataView) {
   27701           5 :   LocalContext env;
   27702           5 :   v8::Isolate* isolate = env->GetIsolate();
   27703          10 :   v8::HandleScope scope(isolate);
   27704           5 :   v8::Local<v8::Context> context = env.local();
   27705             :   Context::Scope context_scope(context);
   27706           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   27707           5 :   v8::Local<v8::DataView> array = v8::DataView::New(buffer, 0, 1);
   27708          15 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   27709          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   27710             :              array->GetAlignedPointerFromInternalField(i));
   27711           5 :   }
   27712           5 : }
   27713             : 
   27714       28342 : TEST(SetPrototypeTemplate) {
   27715           5 :   LocalContext env;
   27716           5 :   v8::Isolate* isolate = env->GetIsolate();
   27717          10 :   v8::HandleScope scope(isolate);
   27718             : 
   27719           5 :   Local<FunctionTemplate> HTMLElementTemplate = FunctionTemplate::New(isolate);
   27720             :   Local<FunctionTemplate> HTMLImageElementTemplate =
   27721           5 :       FunctionTemplate::New(isolate);
   27722           5 :   HTMLImageElementTemplate->Inherit(HTMLElementTemplate);
   27723             : 
   27724           5 :   Local<FunctionTemplate> ImageTemplate = FunctionTemplate::New(isolate);
   27725           5 :   ImageTemplate->SetPrototypeProviderTemplate(HTMLImageElementTemplate);
   27726             : 
   27727             :   Local<Function> HTMLImageElement =
   27728           5 :       HTMLImageElementTemplate->GetFunction(env.local()).ToLocalChecked();
   27729             :   Local<Function> Image =
   27730           5 :       ImageTemplate->GetFunction(env.local()).ToLocalChecked();
   27731             : 
   27732          25 :   CHECK(env->Global()
   27733             :             ->Set(env.local(), v8_str("HTMLImageElement"), HTMLImageElement)
   27734             :             .FromJust());
   27735          25 :   CHECK(env->Global()->Set(env.local(), v8_str("Image"), Image).FromJust());
   27736             : 
   27737           5 :   ExpectTrue("Image.prototype === HTMLImageElement.prototype");
   27738           5 : }
   27739             : 
   27740         120 : void ensure_receiver_is_global_proxy(
   27741             :     v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
   27742         240 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSGlobalProxy());
   27743         120 : }
   27744             : 
   27745       28343 : THREADED_TEST(GlobalAccessorInfo) {
   27746           6 :   v8::Isolate* isolate = CcTest::isolate();
   27747           6 :   v8::HandleScope scope(isolate);
   27748           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   27749             :   global_template->SetAccessor(
   27750             :       v8::String::NewFromUtf8(isolate, "prop", v8::NewStringType::kInternalized)
   27751             :           .ToLocalChecked(),
   27752          12 :       &ensure_receiver_is_global_proxy);
   27753          12 :   LocalContext env(nullptr, global_template);
   27754             :   CompileRun("for (var i = 0; i < 10; i++) this.prop");
   27755           6 :   CompileRun("for (var i = 0; i < 10; i++) prop");
   27756           6 : }
   27757             : 
   27758       28342 : TEST(DeterministicRandomNumberGeneration) {
   27759           5 :   v8::HandleScope scope(CcTest::isolate());
   27760             : 
   27761           5 :   int previous_seed = v8::internal::FLAG_random_seed;
   27762           5 :   v8::internal::FLAG_random_seed = 1234;
   27763             : 
   27764             :   double first_value;
   27765             :   double second_value;
   27766             :   {
   27767           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27768             :     Context::Scope context_scope(context);
   27769             :     v8::Local<Value> result = CompileRun("Math.random();");
   27770          10 :     first_value = result->ToNumber(context).ToLocalChecked()->Value();
   27771             :   }
   27772             :   {
   27773           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27774             :     Context::Scope context_scope(context);
   27775             :     v8::Local<Value> result = CompileRun("Math.random();");
   27776          10 :     second_value = result->ToNumber(context).ToLocalChecked()->Value();
   27777             :   }
   27778           5 :   CHECK_EQ(first_value, second_value);
   27779             : 
   27780           5 :   v8::internal::FLAG_random_seed = previous_seed;
   27781           5 : }
   27782             : 
   27783       28342 : UNINITIALIZED_TEST(AllowAtomicsWait) {
   27784             :   v8::Isolate::CreateParams create_params;
   27785           5 :   create_params.allow_atomics_wait = false;
   27786           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   27787           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   27788          10 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27789             :   {
   27790           5 :     CHECK_EQ(false, i_isolate->allow_atomics_wait());
   27791           5 :     isolate->SetAllowAtomicsWait(true);
   27792           5 :     CHECK_EQ(true, i_isolate->allow_atomics_wait());
   27793             :   }
   27794           5 :   isolate->Dispose();
   27795           5 : }
   27796             : 
   27797             : enum ContextId { EnteredContext, CurrentContext };
   27798             : 
   27799          20 : void CheckContexts(v8::Isolate* isolate) {
   27800          60 :   CHECK_EQ(CurrentContext, isolate->GetCurrentContext()
   27801             :                                ->GetEmbedderData(1)
   27802             :                                .As<v8::Integer>()
   27803             :                                ->Value());
   27804          60 :   CHECK_EQ(EnteredContext, isolate->GetEnteredOrMicrotaskContext()
   27805             :                                ->GetEmbedderData(1)
   27806             :                                .As<v8::Integer>()
   27807             :                                ->Value());
   27808          20 : }
   27809             : 
   27810           5 : void ContextCheckGetter(Local<String> name,
   27811             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   27812           5 :   CheckContexts(info.GetIsolate());
   27813             :   info.GetReturnValue().Set(true);
   27814           5 : }
   27815             : 
   27816           5 : void ContextCheckSetter(Local<String> name, Local<Value>,
   27817             :                         const v8::PropertyCallbackInfo<void>& info) {
   27818           5 :   CheckContexts(info.GetIsolate());
   27819           5 : }
   27820             : 
   27821          20 : void ContextCheckToString(const v8::FunctionCallbackInfo<v8::Value>& info) {
   27822          10 :   CheckContexts(info.GetIsolate());
   27823          10 :   info.GetReturnValue().Set(v8_str("foo"));
   27824          10 : }
   27825             : 
   27826       28342 : TEST(CorrectEnteredContext) {
   27827           5 :   v8::HandleScope scope(CcTest::isolate());
   27828             : 
   27829          10 :   LocalContext currentContext;
   27830             :   currentContext->SetEmbedderData(
   27831          10 :       1, v8::Integer::New(currentContext->GetIsolate(), CurrentContext));
   27832          10 :   LocalContext enteredContext;
   27833             :   enteredContext->SetEmbedderData(
   27834          10 :       1, v8::Integer::New(enteredContext->GetIsolate(), EnteredContext));
   27835             : 
   27836           5 :   v8::Context::Scope contextScope(enteredContext.local());
   27837             : 
   27838             :   v8::Local<v8::ObjectTemplate> object_template =
   27839           5 :       ObjectTemplate::New(currentContext->GetIsolate());
   27840             :   object_template->SetAccessor(v8_str("p"), &ContextCheckGetter,
   27841           5 :                                &ContextCheckSetter);
   27842             : 
   27843             :   v8::Local<v8::Object> object =
   27844           5 :       object_template->NewInstance(currentContext.local()).ToLocalChecked();
   27845             : 
   27846          15 :   object->Get(currentContext.local(), v8_str("p")).ToLocalChecked();
   27847          15 :   object->Set(currentContext.local(), v8_str("p"), v8_int(0)).FromJust();
   27848             : 
   27849             :   v8::Local<v8::Function> to_string =
   27850          10 :       v8::Function::New(currentContext.local(), ContextCheckToString)
   27851           5 :           .ToLocalChecked();
   27852             : 
   27853          10 :   to_string->Call(currentContext.local(), object, 0, nullptr).ToLocalChecked();
   27854             : 
   27855             :   object
   27856             :       ->CreateDataProperty(currentContext.local(), v8_str("toString"),
   27857          15 :                            to_string)
   27858          10 :       .FromJust();
   27859             : 
   27860          10 :   object->ToString(currentContext.local()).ToLocalChecked();
   27861           5 : }
   27862             : 
   27863           5 : v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallbackResolve(
   27864             :     Local<Context> context, Local<v8::ScriptOrModule> referrer,
   27865             :     Local<String> specifier) {
   27866           5 :   CHECK(!referrer.IsEmpty());
   27867             :   String::Utf8Value referrer_utf8(
   27868          10 :       context->GetIsolate(), Local<String>::Cast(referrer->GetResourceName()));
   27869           5 :   CHECK_EQ(0, strcmp("www.google.com", *referrer_utf8));
   27870          15 :   CHECK(referrer->GetHostDefinedOptions()
   27871             :             ->Get(context->GetIsolate(), 0)
   27872             :             ->IsSymbol());
   27873             : 
   27874           5 :   CHECK(!specifier.IsEmpty());
   27875          10 :   String::Utf8Value specifier_utf8(context->GetIsolate(), specifier);
   27876           5 :   CHECK_EQ(0, strcmp("index.js", *specifier_utf8));
   27877             : 
   27878             :   Local<v8::Promise::Resolver> resolver =
   27879           5 :       v8::Promise::Resolver::New(context).ToLocalChecked();
   27880           5 :   auto result = v8_str("hello world");
   27881          10 :   resolver->Resolve(context, result).ToChecked();
   27882          10 :   return resolver->GetPromise();
   27883             : }
   27884             : 
   27885       28342 : TEST(DynamicImport) {
   27886           5 :   i::FLAG_harmony_dynamic_import = true;
   27887           5 :   LocalContext context;
   27888           5 :   v8::Isolate* isolate = context->GetIsolate();
   27889          10 :   v8::HandleScope scope(isolate);
   27890             : 
   27891             :   isolate->SetHostImportModuleDynamicallyCallback(
   27892           5 :       HostImportModuleDynamicallyCallbackResolve);
   27893             : 
   27894          10 :   i::Handle<i::String> url(v8::Utils::OpenHandle(*v8_str("www.google.com")));
   27895          10 :   i::Handle<i::Object> specifier(v8::Utils::OpenHandle(*v8_str("index.js")));
   27896          10 :   i::Handle<i::String> result(v8::Utils::OpenHandle(*v8_str("hello world")));
   27897          10 :   i::Handle<i::String> source(v8::Utils::OpenHandle(*v8_str("foo")));
   27898             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27899           5 :   i::Handle<i::FixedArray> options = i_isolate->factory()->NewFixedArray(1);
   27900           5 :   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewSymbol();
   27901          10 :   options->set(0, *symbol);
   27902           5 :   i::Handle<i::Script> referrer = i_isolate->factory()->NewScript(source);
   27903          10 :   referrer->set_name(*url);
   27904           5 :   referrer->set_host_defined_options(*options);
   27905             :   i::MaybeHandle<i::JSPromise> maybe_promise =
   27906           5 :       i_isolate->RunHostImportModuleDynamicallyCallback(referrer, specifier);
   27907             :   i::Handle<i::JSPromise> promise = maybe_promise.ToHandleChecked();
   27908           5 :   isolate->RunMicrotasks();
   27909          15 :   CHECK(result->Equals(i::String::cast(promise->result())));
   27910           5 : }
   27911             : 
   27912           5 : void HostInitializeImportMetaObjectCallbackStatic(Local<Context> context,
   27913             :                                                   Local<Module> module,
   27914             :                                                   Local<Object> meta) {
   27915           5 :   CHECK(!module.IsEmpty());
   27916             : 
   27917          20 :   meta->CreateDataProperty(context, v8_str("foo"), v8_str("bar")).ToChecked();
   27918           5 : }
   27919             : 
   27920       28342 : TEST(ImportMeta) {
   27921           5 :   i::FLAG_harmony_dynamic_import = true;
   27922           5 :   i::FLAG_harmony_import_meta = true;
   27923           5 :   LocalContext context;
   27924           5 :   v8::Isolate* isolate = context->GetIsolate();
   27925          10 :   v8::HandleScope scope(isolate);
   27926             : 
   27927             :   isolate->SetHostInitializeImportMetaObjectCallback(
   27928           5 :       HostInitializeImportMetaObjectCallbackStatic);
   27929             : 
   27930             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27931           5 :   Local<String> url = v8_str("www.google.com");
   27932           5 :   Local<String> source_text = v8_str("import.meta;");
   27933             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27934             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27935             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27936             :                           Local<v8::Boolean>(), True(isolate));
   27937             :   v8::ScriptCompiler::Source source(source_text, origin);
   27938             :   Local<Module> module =
   27939           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27940             :   i::Handle<i::Object> meta =
   27941             :       i_isolate->RunHostInitializeImportMetaObjectCallback(
   27942           5 :           v8::Utils::OpenHandle(*module));
   27943          10 :   CHECK(meta->IsJSObject());
   27944             :   Local<Object> meta_obj = Local<Object>::Cast(v8::Utils::ToLocal(meta));
   27945          15 :   CHECK(meta_obj->Get(context.local(), v8_str("foo"))
   27946             :             .ToLocalChecked()
   27947             :             ->IsString());
   27948          15 :   CHECK(meta_obj->Get(context.local(), v8_str("zapp"))
   27949             :             .ToLocalChecked()
   27950             :             ->IsUndefined());
   27951             : 
   27952           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27953          10 :       .ToChecked();
   27954           5 :   Local<Value> result = module->Evaluate(context.local()).ToLocalChecked();
   27955          10 :   CHECK(result->StrictEquals(Local<v8::Value>::Cast(v8::Utils::ToLocal(meta))));
   27956           5 : }
   27957             : 
   27958       28342 : TEST(GetModuleNamespace) {
   27959           5 :   LocalContext context;
   27960           5 :   v8::Isolate* isolate = context->GetIsolate();
   27961          10 :   v8::HandleScope scope(isolate);
   27962             : 
   27963           5 :   Local<String> url = v8_str("www.google.com");
   27964           5 :   Local<String> source_text = v8_str("export default 5; export const a = 10;");
   27965             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27966             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27967             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27968             :                           Local<v8::Boolean>(), True(isolate));
   27969             :   v8::ScriptCompiler::Source source(source_text, origin);
   27970             :   Local<Module> module =
   27971           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27972           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27973          10 :       .ToChecked();
   27974           5 :   module->Evaluate(context.local()).ToLocalChecked();
   27975             : 
   27976           5 :   Local<Value> ns_val = module->GetModuleNamespace();
   27977           5 :   CHECK(ns_val->IsModuleNamespaceObject());
   27978             :   Local<Object> ns = ns_val.As<Object>();
   27979          20 :   CHECK(ns->Get(context.local(), v8_str("default"))
   27980             :             .ToLocalChecked()
   27981             :             ->StrictEquals(v8::Number::New(isolate, 5)));
   27982          20 :   CHECK(ns->Get(context.local(), v8_str("a"))
   27983             :             .ToLocalChecked()
   27984           5 :             ->StrictEquals(v8::Number::New(isolate, 10)));
   27985           5 : }
   27986             : 
   27987       28342 : TEST(ModuleGetUnboundModuleScript) {
   27988           5 :   LocalContext context;
   27989           5 :   v8::Isolate* isolate = context->GetIsolate();
   27990          10 :   v8::HandleScope scope(isolate);
   27991             : 
   27992           5 :   Local<String> url = v8_str("www.google.com");
   27993           5 :   Local<String> source_text = v8_str("export default 5; export const a = 10;");
   27994             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27995             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27996             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27997             :                           Local<v8::Boolean>(), True(isolate));
   27998             :   v8::ScriptCompiler::Source source(source_text, origin);
   27999             :   Local<Module> module =
   28000           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   28001             :   Local<v8::UnboundModuleScript> sfi_before_instantiation =
   28002           5 :       module->GetUnboundModuleScript();
   28003           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   28004          10 :       .ToChecked();
   28005             :   Local<v8::UnboundModuleScript> sfi_after_instantiation =
   28006           5 :       module->GetUnboundModuleScript();
   28007             : 
   28008             :   // Check object identity.
   28009             :   {
   28010             :     i::Handle<i::Object> s1 = v8::Utils::OpenHandle(*sfi_before_instantiation);
   28011             :     i::Handle<i::Object> s2 = v8::Utils::OpenHandle(*sfi_after_instantiation);
   28012          15 :     CHECK_EQ(*s1, *s2);
   28013           5 :   }
   28014           5 : }
   28015             : 
   28016       28342 : TEST(GlobalTemplateWithDoubleProperty) {
   28017           5 :   v8::Isolate* isolate = CcTest::isolate();
   28018           5 :   v8::HandleScope handle_scope(isolate);
   28019             : 
   28020           5 :   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   28021          15 :   global->Set(v8_str("double"), v8_num(3.14));
   28022             : 
   28023           5 :   v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
   28024             : 
   28025             :   v8::Context::Scope context_scope(context);
   28026             : 
   28027             :   Local<Value> result = CompileRun("double");
   28028           5 :   CHECK(result->IsNumber());
   28029          15 :   CheckDoubleEquals(3.14, result->NumberValue(context).ToChecked());
   28030           5 : }
   28031             : 
   28032       28342 : TEST(PrimitiveArray) {
   28033           5 :   v8::Isolate* isolate = CcTest::isolate();
   28034           5 :   v8::HandleScope scope(isolate);
   28035          10 :   LocalContext env;
   28036             : 
   28037             :   int length = 5;
   28038           5 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 5));
   28039           5 :   CHECK_EQ(length, array->Length());
   28040             : 
   28041          25 :   for (int i = 0; i < length; i++) {
   28042          25 :     Local<v8::Primitive> item = array->Get(isolate, i);
   28043          25 :     CHECK(item->IsUndefined());
   28044             :   }
   28045             : 
   28046           5 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   28047           5 :   array->Set(isolate, 0, symbol);
   28048          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   28049             : 
   28050             :   Local<v8::String> string =
   28051             :       v8::String::NewFromUtf8(isolate, "test", v8::NewStringType::kInternalized)
   28052           5 :           .ToLocalChecked();
   28053           5 :   array->Set(isolate, 1, string);
   28054          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   28055          10 :   CHECK(array->Get(isolate, 1)->IsString());
   28056             : 
   28057           5 :   Local<v8::Number> num = v8::Number::New(env->GetIsolate(), 3.1415926);
   28058           5 :   array->Set(isolate, 2, num);
   28059          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   28060          10 :   CHECK(array->Get(isolate, 1)->IsString());
   28061          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   28062             : 
   28063             :   v8::Local<v8::Boolean> f = v8::False(isolate);
   28064           5 :   array->Set(isolate, 3, f);
   28065          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   28066          10 :   CHECK(array->Get(isolate, 1)->IsString());
   28067          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   28068          10 :   CHECK(array->Get(isolate, 3)->IsBoolean());
   28069             : 
   28070           5 :   v8::Local<v8::Primitive> n = v8::Null(isolate);
   28071           5 :   array->Set(isolate, 4, n);
   28072          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   28073          10 :   CHECK(array->Get(isolate, 1)->IsString());
   28074          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   28075          10 :   CHECK(array->Get(isolate, 3)->IsBoolean());
   28076          15 :   CHECK(array->Get(isolate, 4)->IsNull());
   28077           5 : }
   28078             : 
   28079       28342 : TEST(PersistentValueMap) {
   28080           5 :   v8::Isolate* isolate = CcTest::isolate();
   28081           5 :   v8::HandleScope scope(isolate);
   28082          10 :   LocalContext env;
   28083             : 
   28084             :   v8::PersistentValueMap<
   28085             :       std::string, v8::Value,
   28086             :       v8::DefaultPersistentValueMapTraits<std::string, v8::Value>>
   28087             :       map(isolate);
   28088             :   v8::Local<v8::Value> value =
   28089             :       v8::String::NewFromUtf8(isolate, "value",
   28090             :                               v8::NewStringType::kInternalized)
   28091           5 :           .ToLocalChecked();
   28092          20 :   map.Set("key", value);
   28093           5 : }
   28094             : 
   28095             : namespace {
   28096             : 
   28097             : bool wasm_streaming_callback_got_called = false;
   28098             : bool wasm_streaming_data_got_collected = false;
   28099             : 
   28100          10 : void WasmStreamingTestFinalizer(const v8::WeakCallbackInfo<void>& data) {
   28101           5 :   CHECK(!wasm_streaming_data_got_collected);
   28102           5 :   wasm_streaming_data_got_collected = true;
   28103           5 :   i::GlobalHandles::Destroy(reinterpret_cast<i::Address*>(data.GetParameter()));
   28104           5 : }
   28105             : 
   28106           5 : void WasmStreamingCallbackTestCallbackIsCalled(
   28107          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   28108           5 :   CHECK(!wasm_streaming_callback_got_called);
   28109           5 :   wasm_streaming_callback_got_called = true;
   28110             : 
   28111             :   i::Handle<i::Object> global_handle =
   28112             :       reinterpret_cast<i::Isolate*>(args.GetIsolate())
   28113             :           ->global_handles()
   28114           5 :           ->Create(*v8::Utils::OpenHandle(*args.Data()));
   28115             :   i::GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
   28116             :                              WasmStreamingTestFinalizer,
   28117           5 :                              v8::WeakCallbackType::kParameter);
   28118           5 : }
   28119             : 
   28120           5 : void WasmStreamingCallbackTestOnBytesReceived(
   28121           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   28122             :   std::shared_ptr<v8::WasmStreaming> streaming =
   28123           5 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   28124             : 
   28125             :   // The first bytes of the WebAssembly magic word.
   28126           5 :   const uint8_t bytes[]{0x00, 0x61, 0x73};
   28127           5 :   streaming->OnBytesReceived(bytes, arraysize(bytes));
   28128           5 : }
   28129             : 
   28130           5 : void WasmStreamingCallbackTestFinishWithSuccess(
   28131           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   28132             :   std::shared_ptr<v8::WasmStreaming> streaming =
   28133           5 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   28134             :   // The bytes of a minimal WebAssembly module.
   28135           5 :   const uint8_t bytes[]{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00};
   28136           5 :   streaming->OnBytesReceived(bytes, arraysize(bytes));
   28137           5 :   streaming->Finish();
   28138           5 : }
   28139             : 
   28140           5 : void WasmStreamingCallbackTestFinishWithFailure(
   28141           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   28142             :   std::shared_ptr<v8::WasmStreaming> streaming =
   28143           5 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   28144           5 :   streaming->Finish();
   28145           5 : }
   28146             : 
   28147           5 : void WasmStreamingCallbackTestAbortWithReject(
   28148          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   28149             :   std::shared_ptr<v8::WasmStreaming> streaming =
   28150           5 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   28151          10 :   streaming->Abort(v8::Object::New(args.GetIsolate()));
   28152           5 : }
   28153             : 
   28154           5 : void WasmStreamingCallbackTestAbortNoReject(
   28155           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   28156             :   std::shared_ptr<v8::WasmStreaming> streaming =
   28157           5 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   28158           5 :   streaming->Abort({});
   28159           5 : }
   28160             : 
   28161          30 : void TestWasmStreaming(v8::WasmStreamingCallback callback,
   28162             :                        v8::Promise::PromiseState expected_state) {
   28163          30 :   CcTest::isolate()->SetWasmStreamingCallback(callback);
   28164          30 :   LocalContext env;
   28165          30 :   v8::Isolate* isolate = env->GetIsolate();
   28166          60 :   v8::HandleScope scope(isolate);
   28167             : 
   28168             :   // Call {WebAssembly.compileStreaming} with {null} as parameter. The parameter
   28169             :   // is only really processed by the embedder, so for this test the value is
   28170             :   // irrelevant.
   28171             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(
   28172             :       CompileRun("WebAssembly.compileStreaming(null)"));
   28173             : 
   28174          30 :   EmptyMessageQueues(isolate);
   28175          60 :   CHECK_EQ(expected_state, promise->State());
   28176          30 : }
   28177             : 
   28178             : }  // namespace
   28179             : 
   28180       28342 : TEST(WasmStreamingCallback) {
   28181             :   TestWasmStreaming(WasmStreamingCallbackTestCallbackIsCalled,
   28182           5 :                     v8::Promise::kPending);
   28183           5 :   CHECK(wasm_streaming_callback_got_called);
   28184           5 :   CcTest::CollectAllAvailableGarbage();
   28185           5 :   CHECK(wasm_streaming_data_got_collected);
   28186           5 : }
   28187             : 
   28188       28342 : TEST(WasmStreamingOnBytesReceived) {
   28189             :   TestWasmStreaming(WasmStreamingCallbackTestOnBytesReceived,
   28190           5 :                     v8::Promise::kPending);
   28191           5 : }
   28192             : 
   28193       28342 : TEST(WasmStreamingFinishWithSuccess) {
   28194             :   TestWasmStreaming(WasmStreamingCallbackTestFinishWithSuccess,
   28195           5 :                     v8::Promise::kFulfilled);
   28196           5 : }
   28197             : 
   28198       28342 : TEST(WasmStreamingFinishWithFailure) {
   28199             :   TestWasmStreaming(WasmStreamingCallbackTestFinishWithFailure,
   28200           5 :                     v8::Promise::kRejected);
   28201           5 : }
   28202             : 
   28203       28342 : TEST(WasmStreamingAbortWithReject) {
   28204             :   TestWasmStreaming(WasmStreamingCallbackTestAbortWithReject,
   28205           5 :                     v8::Promise::kRejected);
   28206           5 : }
   28207             : 
   28208       28342 : TEST(WasmStreamingAbortWithoutReject) {
   28209             :   TestWasmStreaming(WasmStreamingCallbackTestAbortNoReject,
   28210           5 :                     v8::Promise::kPending);
   28211           5 : }
   28212             : 
   28213             : enum class AtomicsWaitCallbackAction {
   28214             :   Interrupt,
   28215             :   StopAndThrowInFirstCall,
   28216             :   StopAndThrowInSecondCall,
   28217             :   StopFromThreadAndThrow,
   28218             :   KeepWaiting
   28219             : };
   28220             : 
   28221             : class StopAtomicsWaitThread;
   28222             : 
   28223          10 : struct AtomicsWaitCallbackInfo {
   28224             :   v8::Isolate* isolate;
   28225             :   v8::Isolate::AtomicsWaitWakeHandle* wake_handle;
   28226             :   std::unique_ptr<StopAtomicsWaitThread> stop_thread;
   28227             :   AtomicsWaitCallbackAction action;
   28228             : 
   28229             :   Local<v8::SharedArrayBuffer> expected_sab;
   28230             :   v8::Isolate::AtomicsWaitEvent expected_event;
   28231             :   double expected_timeout;
   28232             :   int64_t expected_value;
   28233             :   size_t expected_offset;
   28234             : 
   28235             :   size_t ncalls = 0;
   28236             : };
   28237             : 
   28238           5 : class StopAtomicsWaitThread : public v8::base::Thread {
   28239             :  public:
   28240             :   explicit StopAtomicsWaitThread(AtomicsWaitCallbackInfo* info)
   28241           5 :       : Thread(Options("StopAtomicsWaitThread")), info_(info) {}
   28242             : 
   28243           5 :   void Run() override {
   28244           5 :     CHECK_NOT_NULL(info_->wake_handle);
   28245           5 :     info_->wake_handle->Wake();
   28246           5 :   }
   28247             : 
   28248             :  private:
   28249             :   AtomicsWaitCallbackInfo* info_;
   28250             : };
   28251             : 
   28252          65 : void AtomicsWaitCallbackForTesting(
   28253             :     v8::Isolate::AtomicsWaitEvent event, Local<v8::SharedArrayBuffer> sab,
   28254             :     size_t offset_in_bytes, int64_t value, double timeout_in_ms,
   28255             :     v8::Isolate::AtomicsWaitWakeHandle* wake_handle, void* data) {
   28256          65 :   AtomicsWaitCallbackInfo* info = static_cast<AtomicsWaitCallbackInfo*>(data);
   28257          65 :   info->ncalls++;
   28258          65 :   info->wake_handle = wake_handle;
   28259          65 :   CHECK(sab->StrictEquals(info->expected_sab));
   28260          65 :   CHECK_EQ(timeout_in_ms, info->expected_timeout);
   28261          65 :   CHECK_EQ(value, info->expected_value);
   28262          65 :   CHECK_EQ(offset_in_bytes, info->expected_offset);
   28263             : 
   28264          20 :   auto ThrowSomething = [&]() {
   28265          40 :     info->isolate->ThrowException(v8::Integer::New(info->isolate, 42));
   28266          85 :   };
   28267             : 
   28268          65 :   if (event == v8::Isolate::AtomicsWaitEvent::kStartWait) {
   28269          35 :     CHECK_NOT_NULL(wake_handle);
   28270          35 :     switch (info->action) {
   28271             :       case AtomicsWaitCallbackAction::Interrupt:
   28272           5 :         info->isolate->TerminateExecution();
   28273           5 :         break;
   28274             :       case AtomicsWaitCallbackAction::StopAndThrowInFirstCall:
   28275           5 :         ThrowSomething();
   28276             :         V8_FALLTHROUGH;
   28277             :       case AtomicsWaitCallbackAction::StopAndThrowInSecondCall:
   28278          15 :         wake_handle->Wake();
   28279          15 :         break;
   28280             :       case AtomicsWaitCallbackAction::StopFromThreadAndThrow:
   28281          10 :         info->stop_thread = v8::base::make_unique<StopAtomicsWaitThread>(info);
   28282          10 :         info->stop_thread->Start();
   28283           5 :         break;
   28284             :       case AtomicsWaitCallbackAction::KeepWaiting:
   28285             :         break;
   28286             :     }
   28287             :   } else {
   28288          30 :     CHECK_EQ(event, info->expected_event);
   28289          30 :     CHECK_NULL(wake_handle);
   28290             : 
   28291          30 :     if (info->stop_thread) {
   28292           5 :       info->stop_thread->Join();
   28293           5 :       info->stop_thread.reset();
   28294             :     }
   28295             : 
   28296          30 :     if (info->action == AtomicsWaitCallbackAction::StopAndThrowInSecondCall ||
   28297             :         info->action == AtomicsWaitCallbackAction::StopFromThreadAndThrow) {
   28298          15 :       ThrowSomething();
   28299             :     }
   28300             :   }
   28301          65 : }
   28302             : 
   28303       28342 : TEST(AtomicsWaitCallback) {
   28304           5 :   LocalContext env;
   28305           5 :   v8::Isolate* isolate = env->GetIsolate();
   28306          10 :   v8::HandleScope scope(isolate);
   28307             : 
   28308             :   Local<Value> sab = CompileRun(
   28309             :       "sab = new SharedArrayBuffer(12);"
   28310             :       "int32arr = new Int32Array(sab, 4);"
   28311             :       "sab");
   28312           5 :   CHECK(sab->IsSharedArrayBuffer());
   28313             : 
   28314             :   AtomicsWaitCallbackInfo info;
   28315           5 :   info.isolate = isolate;
   28316           5 :   info.expected_sab = sab.As<v8::SharedArrayBuffer>();
   28317           5 :   isolate->SetAtomicsWaitCallback(AtomicsWaitCallbackForTesting, &info);
   28318             : 
   28319             :   {
   28320           5 :     v8::TryCatch try_catch(isolate);
   28321           5 :     info.expected_offset = 4;
   28322           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   28323           5 :     info.expected_value = 0;
   28324           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kTerminatedExecution;
   28325           5 :     info.action = AtomicsWaitCallbackAction::Interrupt;
   28326           5 :     info.ncalls = 0;
   28327             :     CompileRun("Atomics.wait(int32arr, 0, 0);");
   28328          10 :     CHECK_EQ(info.ncalls, 2);
   28329           5 :     CHECK(try_catch.HasTerminated());
   28330             :   }
   28331             : 
   28332             :   {
   28333           5 :     v8::TryCatch try_catch(isolate);
   28334           5 :     info.expected_offset = 8;
   28335           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   28336           5 :     info.expected_value = 1;
   28337           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kNotEqual;
   28338           5 :     info.action = AtomicsWaitCallbackAction::KeepWaiting;
   28339           5 :     info.ncalls = 0;
   28340             :     CompileRun("Atomics.wait(int32arr, 1, 1);");  // real value is 0 != 1
   28341          10 :     CHECK_EQ(info.ncalls, 2);
   28342           5 :     CHECK(!try_catch.HasCaught());
   28343             :   }
   28344             : 
   28345             :   {
   28346           5 :     v8::TryCatch try_catch(isolate);
   28347           5 :     info.expected_offset = 8;
   28348           5 :     info.expected_timeout = 0.125;
   28349           5 :     info.expected_value = 0;
   28350           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kTimedOut;
   28351           5 :     info.action = AtomicsWaitCallbackAction::KeepWaiting;
   28352           5 :     info.ncalls = 0;
   28353             :     CompileRun("Atomics.wait(int32arr, 1, 0, 0.125);");  // timeout
   28354          10 :     CHECK_EQ(info.ncalls, 2);
   28355           5 :     CHECK(!try_catch.HasCaught());
   28356             :   }
   28357             : 
   28358             :   {
   28359           5 :     v8::TryCatch try_catch(isolate);
   28360           5 :     info.expected_offset = 8;
   28361           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   28362           5 :     info.expected_value = 0;
   28363           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   28364           5 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInFirstCall;
   28365           5 :     info.ncalls = 0;
   28366             :     CompileRun("Atomics.wait(int32arr, 1, 0);");
   28367          10 :     CHECK_EQ(info.ncalls, 1);  // Only one extra call
   28368           5 :     CHECK(try_catch.HasCaught());
   28369          10 :     CHECK(try_catch.Exception()->IsInt32());
   28370           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   28371             :   }
   28372             : 
   28373             :   {
   28374           5 :     v8::TryCatch try_catch(isolate);
   28375           5 :     info.expected_offset = 8;
   28376           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   28377           5 :     info.expected_value = 0;
   28378           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   28379           5 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInSecondCall;
   28380           5 :     info.ncalls = 0;
   28381             :     CompileRun("Atomics.wait(int32arr, 1, 0);");
   28382          10 :     CHECK_EQ(info.ncalls, 2);
   28383           5 :     CHECK(try_catch.HasCaught());
   28384          10 :     CHECK(try_catch.Exception()->IsInt32());
   28385           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   28386             :   }
   28387             : 
   28388             :   {
   28389             :     // Same test as before, but with a different `expected_value`.
   28390           5 :     v8::TryCatch try_catch(isolate);
   28391           5 :     info.expected_offset = 8;
   28392           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   28393           5 :     info.expected_value = 200;
   28394           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   28395           5 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInSecondCall;
   28396           5 :     info.ncalls = 0;
   28397             :     CompileRun(
   28398             :         "int32arr[1] = 200;"
   28399             :         "Atomics.wait(int32arr, 1, 200);");
   28400          10 :     CHECK_EQ(info.ncalls, 2);
   28401           5 :     CHECK(try_catch.HasCaught());
   28402          10 :     CHECK(try_catch.Exception()->IsInt32());
   28403           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   28404             :   }
   28405             : 
   28406             :   {
   28407             :     // Wake the `Atomics.wait()` call from a thread.
   28408           5 :     v8::TryCatch try_catch(isolate);
   28409           5 :     info.expected_offset = 4;
   28410           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   28411           5 :     info.expected_value = 0;
   28412           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   28413           5 :     info.action = AtomicsWaitCallbackAction::StopFromThreadAndThrow;
   28414           5 :     info.ncalls = 0;
   28415             :     CompileRun("Atomics.wait(int32arr, 0, 0);");
   28416          10 :     CHECK_EQ(info.ncalls, 2);
   28417           5 :     CHECK(try_catch.HasCaught());
   28418          10 :     CHECK(try_catch.Exception()->IsInt32());
   28419           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   28420           5 :   }
   28421           5 : }
   28422             : 
   28423       28342 : TEST(BigIntAPI) {
   28424           5 :   LocalContext env;
   28425           5 :   v8::Isolate* isolate = env->GetIsolate();
   28426          10 :   v8::HandleScope scope(isolate);
   28427             :   bool lossless;
   28428             :   uint64_t words1[10];
   28429             :   uint64_t words2[10];
   28430             : 
   28431             :   {
   28432             :     Local<Value> bi = CompileRun("12n");
   28433           5 :     CHECK(bi->IsBigInt());
   28434             : 
   28435          10 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 12);
   28436          10 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless), 12);
   28437           5 :     CHECK_EQ(lossless, true);
   28438           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 12);
   28439           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 12);
   28440           5 :     CHECK_EQ(lossless, true);
   28441             :   }
   28442             : 
   28443             :   {
   28444             :     Local<Value> bi = CompileRun("-12n");
   28445           5 :     CHECK(bi->IsBigInt());
   28446             : 
   28447           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), static_cast<uint64_t>(-12));
   28448           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   28449             :              static_cast<uint64_t>(-12));
   28450          10 :     CHECK_EQ(lossless, false);
   28451           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -12);
   28452           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), -12);
   28453           5 :     CHECK_EQ(lossless, true);
   28454             :   }
   28455             : 
   28456             :   {
   28457             :     Local<Value> bi = CompileRun("123456789012345678901234567890n");
   28458           5 :     CHECK(bi->IsBigInt());
   28459             : 
   28460           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 14083847773837265618ULL);
   28461           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   28462             :              14083847773837265618ULL);
   28463          10 :     CHECK_EQ(lossless, false);
   28464           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -4362896299872285998LL);
   28465           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless),
   28466             :              -4362896299872285998LL);
   28467          10 :     CHECK_EQ(lossless, false);
   28468             :   }
   28469             : 
   28470             :   {
   28471             :     Local<Value> bi = CompileRun("-123456789012345678901234567890n");
   28472           5 :     CHECK(bi->IsBigInt());
   28473             : 
   28474           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 4362896299872285998LL);
   28475           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   28476             :              4362896299872285998LL);
   28477          10 :     CHECK_EQ(lossless, false);
   28478           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 4362896299872285998LL);
   28479           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 4362896299872285998LL);
   28480          10 :     CHECK_EQ(lossless, false);
   28481             :   }
   28482             : 
   28483             :   {
   28484             :     Local<v8::BigInt> bi =
   28485           5 :         v8::BigInt::NewFromWords(env.local(), 0, 0, words1).ToLocalChecked();
   28486          10 :     CHECK_EQ(bi->Uint64Value(), 0);
   28487           5 :     CHECK_EQ(bi->WordCount(), 0);
   28488             :   }
   28489             : 
   28490             :   {
   28491           5 :     TryCatch try_catch(isolate);
   28492             :     v8::MaybeLocal<v8::BigInt> bi = v8::BigInt::NewFromWords(
   28493           5 :         env.local(), 0, std::numeric_limits<int>::max(), words1);
   28494           5 :     CHECK(bi.IsEmpty());
   28495           5 :     CHECK(try_catch.HasCaught());
   28496             :   }
   28497             : 
   28498             :   {
   28499           5 :     TryCatch try_catch(isolate);
   28500             :     v8::MaybeLocal<v8::BigInt> bi =
   28501           5 :         v8::BigInt::NewFromWords(env.local(), 0, -1, words1);
   28502           5 :     CHECK(bi.IsEmpty());
   28503           5 :     CHECK(try_catch.HasCaught());
   28504             :   }
   28505             : 
   28506             :   {
   28507           5 :     TryCatch try_catch(isolate);
   28508             :     v8::MaybeLocal<v8::BigInt> bi =
   28509           5 :         v8::BigInt::NewFromWords(env.local(), 0, 1 << 30, words1);
   28510           5 :     CHECK(bi.IsEmpty());
   28511           5 :     CHECK(try_catch.HasCaught());
   28512             :   }
   28513             : 
   28514          15 :   for (int sign_bit = 0; sign_bit <= 1; sign_bit++) {
   28515          10 :     words1[0] = 0xffffffff00000000ULL;
   28516          10 :     words1[1] = 0x00000000ffffffffULL;
   28517             :     v8::Local<v8::BigInt> bi =
   28518          10 :         v8::BigInt::NewFromWords(env.local(), sign_bit, 2, words1)
   28519          10 :             .ToLocalChecked();
   28520          10 :     CHECK_EQ(bi->Uint64Value(&lossless),
   28521             :              sign_bit ? static_cast<uint64_t>(-static_cast<int64_t>(words1[0]))
   28522             :                       : words1[0]);
   28523          20 :     CHECK_EQ(lossless, false);
   28524          10 :     CHECK_EQ(bi->Int64Value(&lossless), sign_bit
   28525             :                                             ? -static_cast<int64_t>(words1[0])
   28526             :                                             : static_cast<int64_t>(words1[0]));
   28527          20 :     CHECK_EQ(lossless, false);
   28528          10 :     CHECK_EQ(bi->WordCount(), 2);
   28529             :     int real_sign_bit;
   28530          10 :     int word_count = arraysize(words2);
   28531          10 :     bi->ToWordsArray(&real_sign_bit, &word_count, words2);
   28532          10 :     CHECK_EQ(real_sign_bit, sign_bit);
   28533          10 :     CHECK_EQ(word_count, 2);
   28534           5 :   }
   28535           5 : }
   28536             : 
   28537             : namespace {
   28538             : 
   28539             : bool wasm_threads_enabled_value = false;
   28540             : 
   28541          10 : bool MockWasmThreadsEnabledCallback(Local<Context>) {
   28542          10 :   return wasm_threads_enabled_value;
   28543             : }
   28544             : 
   28545             : }  // namespace
   28546             : 
   28547       28342 : TEST(TestSetWasmThreadsEnabledCallback) {
   28548           5 :   LocalContext env;
   28549           5 :   v8::Isolate* isolate = env->GetIsolate();
   28550             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   28551          10 :   v8::HandleScope scope(isolate);
   28552           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
   28553           5 :   i::Handle<i::Context> i_context = v8::Utils::OpenHandle(*context);
   28554             : 
   28555             :   // {Isolate::AreWasmThreadsEnabled} calls the callback set by the embedder if
   28556             :   // such a callback exists. Otherwise it returns
   28557             :   // {FLAG_experimental_wasm_threads}. First we test that the flag is returned
   28558             :   // correctly if no callback is set. Then we test that the flag is ignored if
   28559             :   // the callback is set.
   28560             : 
   28561           5 :   i::FLAG_experimental_wasm_threads = false;
   28562           5 :   CHECK(!i_isolate->AreWasmThreadsEnabled(i_context));
   28563             : 
   28564           5 :   i::FLAG_experimental_wasm_threads = true;
   28565           5 :   CHECK(i_isolate->AreWasmThreadsEnabled(i_context));
   28566             : 
   28567           5 :   isolate->SetWasmThreadsEnabledCallback(MockWasmThreadsEnabledCallback);
   28568           5 :   wasm_threads_enabled_value = false;
   28569           5 :   CHECK(!i_isolate->AreWasmThreadsEnabled(i_context));
   28570             : 
   28571           5 :   wasm_threads_enabled_value = true;
   28572           5 :   i::FLAG_experimental_wasm_threads = false;
   28573          10 :   CHECK(i_isolate->AreWasmThreadsEnabled(i_context));
   28574           5 : }
   28575             : 
   28576       28342 : TEST(TestGetUnwindState) {
   28577           5 :   LocalContext env;
   28578           5 :   v8::Isolate* isolate = env->GetIsolate();
   28579             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   28580             : 
   28581           5 :   v8::UnwindState unwind_state = isolate->GetUnwindState();
   28582           5 :   v8::MemoryRange builtins_range = unwind_state.embedded_code_range;
   28583             : 
   28584             :   // Check that each off-heap builtin is within the builtins code range.
   28585             :   if (i::FLAG_embedded_builtins) {
   28586        7560 :     for (int id = 0; id < i::Builtins::builtin_count; id++) {
   28587             :       if (!i::Builtins::IsIsolateIndependent(id)) continue;
   28588        7555 :       i::Code builtin = i_isolate->builtins()->builtin(id);
   28589        7555 :       i::Address start = builtin->InstructionStart();
   28590        7555 :       i::Address end = start + builtin->InstructionSize();
   28591             : 
   28592             :       i::Address builtins_start =
   28593        7555 :           reinterpret_cast<i::Address>(builtins_range.start);
   28594        7555 :       CHECK(start >= builtins_start &&
   28595             :             end < builtins_start + builtins_range.length_in_bytes);
   28596             :     }
   28597             :   } else {
   28598             :     CHECK_EQ(nullptr, builtins_range.start);
   28599             :     CHECK_EQ(0, builtins_range.length_in_bytes);
   28600             :   }
   28601             : 
   28602           5 :   v8::JSEntryStub js_entry_stub = unwind_state.js_entry_stub;
   28603             : 
   28604           5 :   CHECK_EQ(
   28605             :       i_isolate->heap()->builtin(i::Builtins::kJSEntry)->InstructionStart(),
   28606           5 :       reinterpret_cast<i::Address>(js_entry_stub.code.start));
   28607           5 : }
   28608             : 
   28609       28342 : TEST(MicrotaskContextShouldBeNativeContext) {
   28610           5 :   LocalContext env;
   28611           5 :   v8::Isolate* isolate = env->GetIsolate();
   28612          10 :   v8::HandleScope scope(isolate);
   28613             : 
   28614          15 :   auto callback = [](const v8::FunctionCallbackInfo<v8::Value>& info) {
   28615             :     v8::Isolate* isolate = info.GetIsolate();
   28616           5 :     v8::HandleScope scope(isolate);
   28617             :     i::Handle<i::Context> context =
   28618          10 :         v8::Utils::OpenHandle(*isolate->GetEnteredOrMicrotaskContext());
   28619             : 
   28620          10 :     CHECK(context->IsNativeContext());
   28621             :     info.GetReturnValue().SetUndefined();
   28622          10 :   };
   28623             : 
   28624           5 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   28625          10 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(callback);
   28626           5 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   28627           5 :                               .ToLocalChecked()
   28628           5 :                               ->NewInstance(env.local())
   28629             :                               .ToLocalChecked();
   28630             : 
   28631          25 :   CHECK(env->Global()->Set(env.local(), v8_str("callback"), obj).FromJust());
   28632             :   CompileRun(
   28633             :       "with({}){(async ()=>{"
   28634             :       "  await 42;"
   28635             :       "})().then(callback);}");
   28636             : 
   28637          10 :   isolate->RunMicrotasks();
   28638           5 : }
   28639             : 
   28640       28342 : TEST(PreviewSetIteratorEntriesWithDeleted) {
   28641           5 :   LocalContext env;
   28642          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28643           5 :   v8::Local<v8::Context> context = env.local();
   28644             : 
   28645             :   {
   28646             :     // Create set, delete entry, create iterator, preview.
   28647             :     v8::Local<v8::Object> iterator =
   28648             :         CompileRun("var set = new Set([1,2,3]); set.delete(1); set.keys()")
   28649             :             ->ToObject(context)
   28650           5 :             .ToLocalChecked();
   28651             :     bool is_key;
   28652             :     v8::Local<v8::Array> entries =
   28653           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28654           5 :     CHECK(!is_key);
   28655           5 :     CHECK_EQ(2, entries->Length());
   28656          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28657             :                     .ToLocalChecked()
   28658             :                     ->Int32Value(context)
   28659             :                     .FromJust());
   28660          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28661             :                     .ToLocalChecked()
   28662             :                     ->Int32Value(context)
   28663             :                     .FromJust());
   28664             :   }
   28665             :   {
   28666             :     // Create set, create iterator, delete entry, preview.
   28667             :     v8::Local<v8::Object> iterator =
   28668             :         CompileRun("var set = new Set([1,2,3]); set.keys()")
   28669             :             ->ToObject(context)
   28670           5 :             .ToLocalChecked();
   28671             :     CompileRun("set.delete(1);");
   28672             :     bool is_key;
   28673             :     v8::Local<v8::Array> entries =
   28674           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28675           5 :     CHECK(!is_key);
   28676           5 :     CHECK_EQ(2, entries->Length());
   28677          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28678             :                     .ToLocalChecked()
   28679             :                     ->Int32Value(context)
   28680             :                     .FromJust());
   28681          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28682             :                     .ToLocalChecked()
   28683             :                     ->Int32Value(context)
   28684             :                     .FromJust());
   28685             :   }
   28686             :   {
   28687             :     // Create set, create iterator, delete entry, iterate, preview.
   28688             :     v8::Local<v8::Object> iterator =
   28689             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   28690             :             ->ToObject(context)
   28691           5 :             .ToLocalChecked();
   28692             :     CompileRun("set.delete(1); it.next();");
   28693             :     bool is_key;
   28694             :     v8::Local<v8::Array> entries =
   28695           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28696           5 :     CHECK(!is_key);
   28697           5 :     CHECK_EQ(1, entries->Length());
   28698          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28699             :                     .ToLocalChecked()
   28700             :                     ->Int32Value(context)
   28701             :                     .FromJust());
   28702             :   }
   28703             :   {
   28704             :     // Create set, create iterator, delete entry, iterate until empty, preview.
   28705             :     v8::Local<v8::Object> iterator =
   28706             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   28707             :             ->ToObject(context)
   28708           5 :             .ToLocalChecked();
   28709             :     CompileRun("set.delete(1); it.next(); it.next();");
   28710             :     bool is_key;
   28711             :     v8::Local<v8::Array> entries =
   28712           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28713           5 :     CHECK(!is_key);
   28714           5 :     CHECK_EQ(0, entries->Length());
   28715             :   }
   28716             :   {
   28717             :     // Create set, create iterator, delete entry, iterate, trigger rehash,
   28718             :     // preview.
   28719             :     v8::Local<v8::Object> iterator =
   28720             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   28721             :             ->ToObject(context)
   28722           5 :             .ToLocalChecked();
   28723             :     CompileRun("set.delete(1); it.next();");
   28724             :     CompileRun("for (var i = 4; i < 20; i++) set.add(i);");
   28725             :     bool is_key;
   28726             :     v8::Local<v8::Array> entries =
   28727           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28728           5 :     CHECK(!is_key);
   28729           5 :     CHECK_EQ(17, entries->Length());
   28730          85 :     for (uint32_t i = 0; i < 17; i++) {
   28731         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28732             :                           .ToLocalChecked()
   28733             :                           ->Int32Value(context)
   28734             :                           .FromJust());
   28735             :     }
   28736           5 :   }
   28737           5 : }
   28738             : 
   28739       28342 : TEST(PreviewMapIteratorEntriesWithDeleted) {
   28740           5 :   LocalContext env;
   28741          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28742           5 :   v8::Local<v8::Context> context = env.local();
   28743             : 
   28744             :   {
   28745             :     // Create map, delete entry, create iterator, preview.
   28746             :     v8::Local<v8::Object> iterator = CompileRun(
   28747             :                                          "var map = new Map();"
   28748             :                                          "var key = {}; map.set(key, 1);"
   28749             :                                          "map.set({}, 2); map.set({}, 3);"
   28750             :                                          "map.delete(key);"
   28751             :                                          "map.values()")
   28752             :                                          ->ToObject(context)
   28753           5 :                                          .ToLocalChecked();
   28754             :     bool is_key;
   28755             :     v8::Local<v8::Array> entries =
   28756           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28757           5 :     CHECK(!is_key);
   28758           5 :     CHECK_EQ(2, entries->Length());
   28759          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28760             :                     .ToLocalChecked()
   28761             :                     ->Int32Value(context)
   28762             :                     .FromJust());
   28763          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28764             :                     .ToLocalChecked()
   28765             :                     ->Int32Value(context)
   28766             :                     .FromJust());
   28767             :   }
   28768             :   {
   28769             :     // Create map, create iterator, delete entry, preview.
   28770             :     v8::Local<v8::Object> iterator = CompileRun(
   28771             :                                          "var map = new Map();"
   28772             :                                          "var key = {}; map.set(key, 1);"
   28773             :                                          "map.set({}, 2); map.set({}, 3);"
   28774             :                                          "map.values()")
   28775             :                                          ->ToObject(context)
   28776           5 :                                          .ToLocalChecked();
   28777             :     CompileRun("map.delete(key);");
   28778             :     bool is_key;
   28779             :     v8::Local<v8::Array> entries =
   28780           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28781           5 :     CHECK(!is_key);
   28782           5 :     CHECK_EQ(2, entries->Length());
   28783          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28784             :                     .ToLocalChecked()
   28785             :                     ->Int32Value(context)
   28786             :                     .FromJust());
   28787          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28788             :                     .ToLocalChecked()
   28789             :                     ->Int32Value(context)
   28790             :                     .FromJust());
   28791             :   }
   28792             :   {
   28793             :     // Create map, create iterator, delete entry, iterate, preview.
   28794             :     v8::Local<v8::Object> iterator = CompileRun(
   28795             :                                          "var map = new Map();"
   28796             :                                          "var key = {}; map.set(key, 1);"
   28797             :                                          "map.set({}, 2); map.set({}, 3);"
   28798             :                                          "var it = map.values(); it")
   28799             :                                          ->ToObject(context)
   28800           5 :                                          .ToLocalChecked();
   28801             :     CompileRun("map.delete(key); it.next();");
   28802             :     bool is_key;
   28803             :     v8::Local<v8::Array> entries =
   28804           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28805           5 :     CHECK(!is_key);
   28806           5 :     CHECK_EQ(1, entries->Length());
   28807          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28808             :                     .ToLocalChecked()
   28809             :                     ->Int32Value(context)
   28810             :                     .FromJust());
   28811             :   }
   28812             :   {
   28813             :     // Create map, create iterator, delete entry, iterate until empty, preview.
   28814             :     v8::Local<v8::Object> iterator = CompileRun(
   28815             :                                          "var map = new Map();"
   28816             :                                          "var key = {}; map.set(key, 1);"
   28817             :                                          "map.set({}, 2); map.set({}, 3);"
   28818             :                                          "var it = map.values(); it")
   28819             :                                          ->ToObject(context)
   28820           5 :                                          .ToLocalChecked();
   28821             :     CompileRun("map.delete(key); it.next(); it.next();");
   28822             :     bool is_key;
   28823             :     v8::Local<v8::Array> entries =
   28824           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28825           5 :     CHECK(!is_key);
   28826           5 :     CHECK_EQ(0, entries->Length());
   28827             :   }
   28828             :   {
   28829             :     // Create map, create iterator, delete entry, iterate, trigger rehash,
   28830             :     // preview.
   28831             :     v8::Local<v8::Object> iterator = CompileRun(
   28832             :                                          "var map = new Map();"
   28833             :                                          "var key = {}; map.set(key, 1);"
   28834             :                                          "map.set({}, 2); map.set({}, 3);"
   28835             :                                          "var it = map.values(); it")
   28836             :                                          ->ToObject(context)
   28837           5 :                                          .ToLocalChecked();
   28838             :     CompileRun("map.delete(key); it.next();");
   28839             :     CompileRun("for (var i = 4; i < 20; i++) map.set({}, i);");
   28840             :     bool is_key;
   28841             :     v8::Local<v8::Array> entries =
   28842           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28843           5 :     CHECK(!is_key);
   28844           5 :     CHECK_EQ(17, entries->Length());
   28845          85 :     for (uint32_t i = 0; i < 17; i++) {
   28846         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28847             :                           .ToLocalChecked()
   28848             :                           ->Int32Value(context)
   28849             :                           .FromJust());
   28850             :     }
   28851           5 :   }
   28852           5 : }
   28853             : 
   28854             : namespace {
   28855             : static v8::Isolate* isolate_1;
   28856             : static v8::Isolate* isolate_2;
   28857       28337 : v8::Persistent<v8::Context> context_1;
   28858       28337 : v8::Persistent<v8::Context> context_2;
   28859             : 
   28860          20 : static void CallIsolate1(const v8::FunctionCallbackInfo<v8::Value>& args) {
   28861          20 :   v8::Isolate::Scope isolate_scope(isolate_1);
   28862          40 :   v8::HandleScope handle_scope(isolate_1);
   28863             :   v8::Local<v8::Context> context =
   28864          20 :       v8::Local<v8::Context>::New(isolate_1, context_1);
   28865             :   v8::Context::Scope context_scope(context);
   28866             :   CompileRun("f1() //# sourceURL=isolate1b");
   28867          20 : }
   28868             : 
   28869          20 : static void CallIsolate2(const v8::FunctionCallbackInfo<v8::Value>& args) {
   28870          20 :   v8::Isolate::Scope isolate_scope(isolate_2);
   28871          40 :   v8::HandleScope handle_scope(isolate_2);
   28872             :   v8::Local<v8::Context> context =
   28873          20 :       v8::Local<v8::Context>::New(isolate_2, context_2);
   28874             :   v8::Context::Scope context_scope(context);
   28875             :   reinterpret_cast<i::Isolate*>(isolate_2)->heap()->CollectAllGarbage(
   28876             :       i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting,
   28877          20 :       v8::kGCCallbackFlagForced);
   28878             :   CompileRun("f2() //# sourceURL=isolate2b");
   28879          20 : }
   28880             : 
   28881             : }  // anonymous namespace
   28882             : 
   28883       28342 : UNINITIALIZED_TEST(NestedIsolates) {
   28884             : #ifdef VERIFY_HEAP
   28885             :   i::FLAG_verify_heap = true;
   28886             : #endif  // VERIFY_HEAP
   28887             :   // Create two isolates and set up C++ functions via function templates that
   28888             :   // call into the other isolate. Recurse a few times, trigger GC along the way,
   28889             :   // and finally capture a stack trace. Check that the stack trace only includes
   28890             :   // frames from its own isolate.
   28891             :   v8::Isolate::CreateParams create_params;
   28892           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   28893           5 :   isolate_1 = v8::Isolate::New(create_params);
   28894           5 :   isolate_2 = v8::Isolate::New(create_params);
   28895             : 
   28896             :   {
   28897           5 :     v8::Isolate::Scope isolate_scope(isolate_1);
   28898          10 :     v8::HandleScope handle_scope(isolate_1);
   28899             : 
   28900           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate_1);
   28901             :     v8::Context::Scope context_scope(context);
   28902             : 
   28903             :     v8::Local<v8::FunctionTemplate> fun_templ =
   28904           5 :         v8::FunctionTemplate::New(isolate_1, CallIsolate2);
   28905           5 :     fun_templ->SetClassName(v8_str(isolate_1, "call_isolate_2"));
   28906           5 :     Local<Function> fun = fun_templ->GetFunction(context).ToLocalChecked();
   28907          20 :     CHECK(context->Global()
   28908             :               ->Set(context, v8_str(isolate_1, "call_isolate_2"), fun)
   28909             :               .FromJust());
   28910             :     CompileRun(
   28911             :         "let c = 0;"
   28912             :         "function f1() {"
   28913             :         "  c++;"
   28914             :         "  return call_isolate_2();"
   28915             :         "} //# sourceURL=isolate1a");
   28916           5 :     context_1.Reset(isolate_1, context);
   28917             :   }
   28918             : 
   28919             :   {
   28920           5 :     v8::Isolate::Scope isolate_scope(isolate_2);
   28921          10 :     v8::HandleScope handle_scope(isolate_2);
   28922             : 
   28923           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate_2);
   28924             :     v8::Context::Scope context_scope(context);
   28925             : 
   28926             :     v8::Local<v8::FunctionTemplate> fun_templ =
   28927           5 :         v8::FunctionTemplate::New(isolate_2, CallIsolate1);
   28928           5 :     fun_templ->SetClassName(v8_str(isolate_2, "call_isolate_1"));
   28929           5 :     Local<Function> fun = fun_templ->GetFunction(context).ToLocalChecked();
   28930             : 
   28931          20 :     CHECK(context->Global()
   28932             :               ->Set(context, v8_str(isolate_2, "call_isolate_1"), fun)
   28933             :               .FromJust());
   28934             :     CompileRun(
   28935             :         "let c = 4;"
   28936             :         "let result = undefined;"
   28937             :         "function f2() {"
   28938             :         "  if (c-- > 0) return call_isolate_1();"
   28939             :         "  else result = new Error().stack;"
   28940             :         "} //# sourceURL=isolate2a");
   28941           5 :     context_2.Reset(isolate_2, context);
   28942             : 
   28943             :     v8::Local<v8::String> result =
   28944             :         CompileRun("f2(); result //# sourceURL=isolate2c")
   28945             :             ->ToString(context)
   28946           5 :             .ToLocalChecked();
   28947             :     v8::Local<v8::String> expectation = v8_str(isolate_2,
   28948             :                                                "Error\n"
   28949             :                                                "    at f2 (isolate2a:1:104)\n"
   28950             :                                                "    at isolate2b:1:1\n"
   28951             :                                                "    at f2 (isolate2a:1:71)\n"
   28952             :                                                "    at isolate2b:1:1\n"
   28953             :                                                "    at f2 (isolate2a:1:71)\n"
   28954             :                                                "    at isolate2b:1:1\n"
   28955             :                                                "    at f2 (isolate2a:1:71)\n"
   28956             :                                                "    at isolate2b:1:1\n"
   28957             :                                                "    at f2 (isolate2a:1:71)\n"
   28958           5 :                                                "    at isolate2c:1:1");
   28959           5 :     CHECK(result->StrictEquals(expectation));
   28960             :   }
   28961             : 
   28962             :   {
   28963           5 :     v8::Isolate::Scope isolate_scope(isolate_1);
   28964          10 :     v8::HandleScope handle_scope(isolate_1);
   28965             :     v8::Local<v8::Context> context =
   28966           5 :         v8::Local<v8::Context>::New(isolate_1, context_1);
   28967             :     v8::Context::Scope context_scope(context);
   28968           5 :     ExpectInt32("c", 4);
   28969             :   }
   28970             : 
   28971           5 :   isolate_1->Dispose();
   28972           5 :   isolate_2->Dispose();
   28973       85016 : }

Generated by: LCOV version 1.10