LCOV - code coverage report
Current view: top level - test/cctest - test-api.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 13809 13890 99.4 %
Date: 2019-02-19 Functions: 1103 1170 94.3 %

          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/feedback-vector-inl.h"
      49             : #include "src/feedback-vector.h"
      50             : #include "src/futex-emulation.h"
      51             : #include "src/global-handles.h"
      52             : #include "src/heap/heap-inl.h"
      53             : #include "src/heap/incremental-marking.h"
      54             : #include "src/heap/local-allocator.h"
      55             : #include "src/lookup.h"
      56             : #include "src/objects-inl.h"
      57             : #include "src/objects/hash-table-inl.h"
      58             : #include "src/objects/js-array-buffer-inl.h"
      59             : #include "src/objects/js-array-inl.h"
      60             : #include "src/objects/js-promise-inl.h"
      61             : #include "src/profiler/cpu-profiler.h"
      62             : #include "src/unicode-inl.h"
      63             : #include "src/utils.h"
      64             : #include "src/vm-state.h"
      65             : #include "src/wasm/wasm-js.h"
      66             : #include "test/cctest/heap/heap-tester.h"
      67             : #include "test/cctest/heap/heap-utils.h"
      68             : 
      69             : static const bool kLogThreading = false;
      70             : 
      71             : using ::v8::Array;
      72             : using ::v8::Boolean;
      73             : using ::v8::BooleanObject;
      74             : using ::v8::Context;
      75             : using ::v8::Extension;
      76             : using ::v8::Function;
      77             : using ::v8::FunctionTemplate;
      78             : using ::v8::HandleScope;
      79             : using ::v8::Local;
      80             : using ::v8::Maybe;
      81             : using ::v8::Message;
      82             : using ::v8::MessageCallback;
      83             : using ::v8::Module;
      84             : using ::v8::Name;
      85             : using ::v8::None;
      86             : using ::v8::Object;
      87             : using ::v8::ObjectTemplate;
      88             : using ::v8::Persistent;
      89             : using ::v8::PropertyAttribute;
      90             : using ::v8::Script;
      91             : using ::v8::StackTrace;
      92             : using ::v8::String;
      93             : using ::v8::Symbol;
      94             : using ::v8::TryCatch;
      95             : using ::v8::Undefined;
      96             : using ::v8::V8;
      97             : using ::v8::Value;
      98             : 
      99             : 
     100             : #define THREADED_PROFILED_TEST(Name)                                 \
     101             :   static void Test##Name();                                          \
     102             :   TEST(Name##WithProfiler) {                                         \
     103             :     RunWithProfiler(&Test##Name);                                    \
     104             :   }                                                                  \
     105             :   THREADED_TEST(Name)
     106             : 
     107          30 : void RunWithProfiler(void (*test)()) {
     108          30 :   LocalContext env;
     109          60 :   v8::HandleScope scope(env->GetIsolate());
     110          30 :   v8::Local<v8::String> profile_name = v8_str("my_profile1");
     111          30 :   v8::CpuProfiler* cpu_profiler = v8::CpuProfiler::New(env->GetIsolate());
     112          30 :   cpu_profiler->StartProfiling(profile_name);
     113          30 :   (*test)();
     114          30 :   reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
     115          60 :   cpu_profiler->Dispose();
     116          30 : }
     117             : 
     118             : 
     119             : static int signature_callback_count;
     120             : static Local<Value> signature_expected_receiver;
     121        3900 : static void IncrementingSignatureCallback(
     122       28080 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     123        3900 :   ApiTestFuzzer::Fuzz();
     124        3900 :   signature_callback_count++;
     125       11700 :   CHECK(signature_expected_receiver->Equals(
     126             :                                        args.GetIsolate()->GetCurrentContext(),
     127             :                                        args.Holder())
     128             :             .FromJust());
     129       11700 :   CHECK(signature_expected_receiver->Equals(
     130             :                                        args.GetIsolate()->GetCurrentContext(),
     131             :                                        args.This())
     132             :             .FromJust());
     133             :   v8::Local<v8::Array> result =
     134        3900 :       v8::Array::New(args.GetIsolate(), args.Length());
     135       10920 :   for (int i = 0; i < args.Length(); i++) {
     136        6240 :     CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
     137             :                       v8::Integer::New(args.GetIsolate(), i), args[i])
     138             :               .FromJust());
     139             :   }
     140             :   args.GetReturnValue().Set(result);
     141        3900 : }
     142             : 
     143             : 
     144         205 : static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
     145             :   info.GetReturnValue().Set(42);
     146         205 : }
     147             : 
     148             : 
     149             : // Tests that call v8::V8::Dispose() cannot be threaded.
     150       25880 : UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
     151           5 :   CHECK(v8::V8::Initialize());
     152           5 :   CHECK(v8::V8::Dispose());
     153           5 : }
     154             : 
     155             : 
     156             : // Tests that call v8::V8::Dispose() cannot be threaded.
     157       25880 : UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
     158           5 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     159          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     160          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     161          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
     162          15 :   for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
     163           5 : }
     164             : 
     165             : // Tests that Smi::kZero is set up properly.
     166       25885 : UNINITIALIZED_TEST(SmiZero) { CHECK_EQ(i::Smi::kZero, i::Smi::kZero); }
     167             : 
     168       25881 : THREADED_TEST(Handles) {
     169           6 :   v8::HandleScope scope(CcTest::isolate());
     170             :   Local<Context> local_env;
     171             :   {
     172           6 :     LocalContext env;
     173           6 :     local_env = env.local();
     174             :   }
     175             : 
     176             :   // Local context should still be live.
     177           6 :   CHECK(!local_env.IsEmpty());
     178           6 :   local_env->Enter();
     179             : 
     180           6 :   v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
     181           6 :   CHECK(!undef.IsEmpty());
     182           6 :   CHECK(undef->IsUndefined());
     183             : 
     184             :   const char* source = "1 + 2 + 3";
     185           6 :   Local<Script> script = v8_compile(source);
     186           6 :   CHECK_EQ(6, v8_run_int32value(script));
     187             : 
     188           6 :   local_env->Exit();
     189           6 : }
     190             : 
     191             : 
     192       25881 : THREADED_TEST(IsolateOfContext) {
     193           6 :   v8::HandleScope scope(CcTest::isolate());
     194           6 :   v8::Local<Context> env = Context::New(CcTest::isolate());
     195             : 
     196           6 :   CHECK(!env->GetIsolate()->InContext());
     197           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     198           6 :   env->Enter();
     199           6 :   CHECK(env->GetIsolate()->InContext());
     200           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     201           6 :   env->Exit();
     202           6 :   CHECK(!env->GetIsolate()->InContext());
     203           6 :   CHECK(env->GetIsolate() == CcTest::isolate());
     204           6 : }
     205             : 
     206         420 : static void TestSignatureLooped(const char* operation, Local<Value> receiver,
     207             :                                 v8::Isolate* isolate) {
     208             :   i::ScopedVector<char> source(200);
     209             :   i::SNPrintF(source,
     210             :               "for (var i = 0; i < 10; i++) {"
     211             :               "  %s"
     212             :               "}",
     213         420 :               operation);
     214         420 :   signature_callback_count = 0;
     215         420 :   signature_expected_receiver = receiver;
     216             :   bool expected_to_throw = receiver.IsEmpty();
     217         840 :   v8::TryCatch try_catch(isolate);
     218             :   CompileRun(source.start());
     219         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     220         420 :   if (!expected_to_throw) {
     221         300 :     CHECK_EQ(10, signature_callback_count);
     222             :   } else {
     223         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     224             :               ->Equals(isolate->GetCurrentContext(),
     225             :                        try_catch.Exception()
     226             :                            ->ToString(isolate->GetCurrentContext())
     227             :                            .ToLocalChecked())
     228             :               .FromJust());
     229             :   }
     230         420 : }
     231             : 
     232         420 : static void TestSignatureOptimized(const char* operation, Local<Value> receiver,
     233             :                                    v8::Isolate* isolate) {
     234             :   i::ScopedVector<char> source(200);
     235             :   i::SNPrintF(source,
     236             :               "function test() {"
     237             :               "  %s"
     238             :               "}"
     239             :               "try { test() } catch(e) {}"
     240             :               "try { test() } catch(e) {}"
     241             :               "%%OptimizeFunctionOnNextCall(test);"
     242             :               "test()",
     243         420 :               operation);
     244         420 :   signature_callback_count = 0;
     245         420 :   signature_expected_receiver = receiver;
     246             :   bool expected_to_throw = receiver.IsEmpty();
     247         840 :   v8::TryCatch try_catch(isolate);
     248             :   CompileRun(source.start());
     249         420 :   CHECK_EQ(expected_to_throw, try_catch.HasCaught());
     250         420 :   if (!expected_to_throw) {
     251         300 :     CHECK_EQ(3, signature_callback_count);
     252             :   } else {
     253         600 :     CHECK(v8_str("TypeError: Illegal invocation")
     254             :               ->Equals(isolate->GetCurrentContext(),
     255             :                        try_catch.Exception()
     256             :                            ->ToString(isolate->GetCurrentContext())
     257             :                            .ToLocalChecked())
     258             :               .FromJust());
     259             :   }
     260         420 : }
     261             : 
     262         420 : static void TestSignature(const char* operation, Local<Value> receiver,
     263             :                           v8::Isolate* isolate) {
     264         420 :   TestSignatureLooped(operation, receiver, isolate);
     265         420 :   TestSignatureOptimized(operation, receiver, isolate);
     266         420 : }
     267             : 
     268       25881 : THREADED_TEST(ReceiverSignature) {
     269           6 :   i::FLAG_allow_natives_syntax = true;
     270           6 :   LocalContext env;
     271           6 :   v8::Isolate* isolate = env->GetIsolate();
     272          12 :   v8::HandleScope scope(isolate);
     273             :   // Setup templates.
     274           6 :   v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
     275           6 :   v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
     276             :   v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
     277           6 :       isolate, IncrementingSignatureCallback, Local<Value>(), sig);
     278             :   v8::Local<v8::FunctionTemplate> callback =
     279           6 :       v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
     280           6 :   v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
     281           6 :   sub_fun->Inherit(fun);
     282             :   v8::Local<v8::FunctionTemplate> direct_sub_fun =
     283           6 :       v8::FunctionTemplate::New(isolate);
     284           6 :   direct_sub_fun->Inherit(fun);
     285             :   v8::Local<v8::FunctionTemplate> unrel_fun =
     286           6 :       v8::FunctionTemplate::New(isolate);
     287             :   // Install properties.
     288           6 :   v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
     289          12 :   fun_proto->Set(v8_str("prop_sig"), callback_sig);
     290          12 :   fun_proto->Set(v8_str("prop"), callback);
     291             :   fun_proto->SetAccessorProperty(
     292          12 :       v8_str("accessor_sig"), callback_sig, callback_sig);
     293          12 :   fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
     294             :   // Instantiate templates.
     295             :   Local<Value> fun_instance =
     296          18 :       fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     297             :   Local<Value> sub_fun_instance =
     298          18 :       sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
     299             :   // Instance template with properties.
     300             :   v8::Local<v8::ObjectTemplate> direct_instance_templ =
     301           6 :       direct_sub_fun->InstanceTemplate();
     302          12 :   direct_instance_templ->Set(v8_str("prop_sig"), callback_sig);
     303          12 :   direct_instance_templ->Set(v8_str("prop"), callback);
     304             :   direct_instance_templ->SetAccessorProperty(v8_str("accessor_sig"),
     305          12 :                                              callback_sig, callback_sig);
     306             :   direct_instance_templ->SetAccessorProperty(v8_str("accessor"), callback,
     307          12 :                                              callback);
     308             :   Local<Value> direct_instance =
     309           6 :       direct_instance_templ->NewInstance(env.local()).ToLocalChecked();
     310             :   // Setup global variables.
     311          36 :   CHECK(env->Global()
     312             :             ->Set(env.local(), v8_str("Fun"),
     313             :                   fun->GetFunction(env.local()).ToLocalChecked())
     314             :             .FromJust());
     315          42 :   CHECK(env->Global()
     316             :             ->Set(env.local(), v8_str("UnrelFun"),
     317             :                   unrel_fun->GetFunction(env.local()).ToLocalChecked())
     318             :             .FromJust());
     319          30 :   CHECK(env->Global()
     320             :             ->Set(env.local(), v8_str("fun_instance"), fun_instance)
     321             :             .FromJust());
     322          30 :   CHECK(env->Global()
     323             :             ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
     324             :             .FromJust());
     325          30 :   CHECK(env->Global()
     326             :             ->Set(env.local(), v8_str("direct_instance"), direct_instance)
     327             :             .FromJust());
     328             :   CompileRun(
     329             :       "var accessor_sig_key = 'accessor_sig';"
     330             :       "var accessor_key = 'accessor';"
     331             :       "var prop_sig_key = 'prop_sig';"
     332             :       "var prop_key = 'prop';"
     333             :       ""
     334             :       "function copy_props(obj) {"
     335             :       "  var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
     336             :       "  var source = Fun.prototype;"
     337             :       "  for (var i in keys) {"
     338             :       "    var key = keys[i];"
     339             :       "    var desc = Object.getOwnPropertyDescriptor(source, key);"
     340             :       "    Object.defineProperty(obj, key, desc);"
     341             :       "  }"
     342             :       "}"
     343             :       ""
     344             :       "var plain = {};"
     345             :       "copy_props(plain);"
     346             :       "var unrelated = new UnrelFun();"
     347             :       "copy_props(unrelated);"
     348             :       "var inherited = { __proto__: fun_instance };"
     349             :       "var inherited_direct = { __proto__: direct_instance };");
     350             :   // Test with and without ICs
     351             :   const char* test_objects[] = {
     352             :       "fun_instance", "sub_fun_instance", "direct_instance", "plain",
     353           6 :       "unrelated",    "inherited",        "inherited_direct"};
     354             :   unsigned bad_signature_start_offset = 3;
     355          48 :   for (unsigned i = 0; i < arraysize(test_objects); i++) {
     356             :     i::ScopedVector<char> source(200);
     357             :     i::SNPrintF(
     358          42 :         source, "var test_object = %s; test_object", test_objects[i]);
     359          42 :     Local<Value> test_object = CompileRun(source.start());
     360          42 :     TestSignature("test_object.prop();", test_object, isolate);
     361          42 :     TestSignature("test_object.accessor;", test_object, isolate);
     362          42 :     TestSignature("test_object[accessor_key];", test_object, isolate);
     363          42 :     TestSignature("test_object.accessor = 1;", test_object, isolate);
     364          42 :     TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
     365          42 :     if (i >= bad_signature_start_offset) test_object = Local<Value>();
     366          42 :     TestSignature("test_object.prop_sig();", test_object, isolate);
     367          42 :     TestSignature("test_object.accessor_sig;", test_object, isolate);
     368          42 :     TestSignature("test_object[accessor_sig_key];", test_object, isolate);
     369          42 :     TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
     370          42 :     TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
     371           6 :   }
     372           6 : }
     373             : 
     374             : 
     375       25881 : THREADED_TEST(HulIgennem) {
     376           6 :   LocalContext env;
     377           6 :   v8::Isolate* isolate = env->GetIsolate();
     378          12 :   v8::HandleScope scope(isolate);
     379             :   v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
     380           6 :   Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
     381           6 :   char* value = i::NewArray<char>(undef_str->Utf8Length(isolate) + 1);
     382           6 :   undef_str->WriteUtf8(isolate, value);
     383           6 :   CHECK_EQ(0, strcmp(value, "undefined"));
     384           6 :   i::DeleteArray(value);
     385           6 : }
     386             : 
     387             : 
     388       25881 : THREADED_TEST(Access) {
     389           6 :   LocalContext env;
     390           6 :   v8::Isolate* isolate = env->GetIsolate();
     391          12 :   v8::HandleScope scope(isolate);
     392           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
     393             :   Local<Value> foo_before =
     394          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     395           6 :   CHECK(foo_before->IsUndefined());
     396           6 :   Local<String> bar_str = v8_str("bar");
     397          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
     398             :   Local<Value> foo_after =
     399          18 :       obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
     400           6 :   CHECK(!foo_after->IsUndefined());
     401           6 :   CHECK(foo_after->IsString());
     402          12 :   CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
     403             : 
     404          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).ToChecked());
     405             :   bool result;
     406          18 :   CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).To(&result));
     407          12 :   CHECK(result);
     408           6 : }
     409             : 
     410             : 
     411       25881 : THREADED_TEST(AccessElement) {
     412           6 :   LocalContext env;
     413          12 :   v8::HandleScope scope(env->GetIsolate());
     414           6 :   Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
     415           6 :   Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
     416           6 :   CHECK(before->IsUndefined());
     417           6 :   Local<String> bar_str = v8_str("bar");
     418          12 :   CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
     419           6 :   Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
     420           6 :   CHECK(!after->IsUndefined());
     421           6 :   CHECK(after->IsString());
     422          12 :   CHECK(bar_str->Equals(env.local(), after).FromJust());
     423             : 
     424             :   Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
     425          24 :   CHECK(v8_str("a")
     426             :             ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
     427             :             .FromJust());
     428          24 :   CHECK(v8_str("b")
     429             :             ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
     430           6 :             .FromJust());
     431           6 : }
     432             : 
     433             : 
     434       25881 : THREADED_TEST(Script) {
     435           6 :   LocalContext env;
     436          12 :   v8::HandleScope scope(env->GetIsolate());
     437             :   const char* source = "1 + 2 + 3";
     438           6 :   Local<Script> script = v8_compile(source);
     439          12 :   CHECK_EQ(6, v8_run_int32value(script));
     440           6 : }
     441             : 
     442             : 
     443             : class TestResource: public String::ExternalStringResource {
     444             :  public:
     445             :   explicit TestResource(uint16_t* data, int* counter = nullptr,
     446             :                         bool owning_data = true)
     447       17941 :       : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
     448     3064640 :     while (data[length_]) ++length_;
     449             :   }
     450             : 
     451       35876 :   ~TestResource() override {
     452       17941 :     if (owning_data_) i::DeleteArray(data_);
     453       17941 :     if (counter_ != nullptr) ++*counter_;
     454       35876 :   }
     455             : 
     456       56653 :   const uint16_t* data() const override { return data_; }
     457             : 
     458       71698 :   size_t length() const override { return length_; }
     459             : 
     460             :  private:
     461             :   uint16_t* data_;
     462             :   size_t length_;
     463             :   int* counter_;
     464             :   bool owning_data_;
     465             : };
     466             : 
     467             : 
     468             : class TestOneByteResource : public String::ExternalOneByteStringResource {
     469             :  public:
     470             :   explicit TestOneByteResource(const char* data, int* counter = nullptr,
     471             :                                size_t offset = 0)
     472             :       : orig_data_(data),
     473          10 :         data_(data + offset),
     474          69 :         length_(strlen(data) - offset),
     475         148 :         counter_(counter) {}
     476             : 
     477         128 :   ~TestOneByteResource() override {
     478          69 :     i::DeleteArray(orig_data_);
     479          69 :     if (counter_ != nullptr) ++*counter_;
     480         128 :   }
     481             : 
     482         194 :   const char* data() const override { return data_; }
     483             : 
     484         183 :   size_t length() const override { return length_; }
     485             : 
     486             :  private:
     487             :   const char* orig_data_;
     488             :   const char* data_;
     489             :   size_t length_;
     490             :   int* counter_;
     491             : };
     492             : 
     493             : 
     494       25881 : THREADED_TEST(ScriptUsingStringResource) {
     495           6 :   int dispose_count = 0;
     496             :   const char* c_source = "1 + 2 * 3";
     497           6 :   uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
     498             :   {
     499           6 :     LocalContext env;
     500          12 :     v8::HandleScope scope(env->GetIsolate());
     501           6 :     TestResource* resource = new TestResource(two_byte_source, &dispose_count);
     502             :     Local<String> source =
     503           6 :         String::NewExternalTwoByte(env->GetIsolate(), resource)
     504           6 :             .ToLocalChecked();
     505           6 :     Local<Script> script = v8_compile(source);
     506          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     507           6 :     CHECK(value->IsNumber());
     508          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     509           6 :     CHECK(source->IsExternal());
     510           6 :     CHECK_EQ(resource,
     511             :              static_cast<TestResource*>(source->GetExternalStringResource()));
     512           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     513           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     514             :              source->GetExternalStringResourceBase(&encoding));
     515           6 :     CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
     516           6 :     CcTest::CollectAllGarbage();
     517          12 :     CHECK_EQ(0, dispose_count);
     518             :   }
     519           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     520           6 :   CcTest::CollectAllAvailableGarbage();
     521           6 :   CHECK_EQ(1, dispose_count);
     522           6 : }
     523             : 
     524             : 
     525       25881 : THREADED_TEST(ScriptUsingOneByteStringResource) {
     526           6 :   int dispose_count = 0;
     527             :   const char* c_source = "1 + 2 * 3";
     528             :   {
     529           6 :     LocalContext env;
     530          12 :     v8::HandleScope scope(env->GetIsolate());
     531             :     TestOneByteResource* resource =
     532           6 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count);
     533             :     Local<String> source =
     534           6 :         String::NewExternalOneByte(env->GetIsolate(), resource)
     535           6 :             .ToLocalChecked();
     536           6 :     CHECK(source->IsExternalOneByte());
     537           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     538             :              source->GetExternalOneByteStringResource());
     539           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     540           6 :     CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
     541             :              source->GetExternalStringResourceBase(&encoding));
     542           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     543           6 :     Local<Script> script = v8_compile(source);
     544          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     545           6 :     CHECK(value->IsNumber());
     546          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     547           6 :     CcTest::CollectAllGarbage();
     548          12 :     CHECK_EQ(0, dispose_count);
     549             :   }
     550           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     551           6 :   CcTest::CollectAllAvailableGarbage();
     552           6 :   CHECK_EQ(1, dispose_count);
     553           6 : }
     554             : 
     555             : 
     556       25881 : THREADED_TEST(ScriptMakingExternalString) {
     557           6 :   int dispose_count = 0;
     558           6 :   uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
     559             :   {
     560           6 :     LocalContext env;
     561          12 :     v8::HandleScope scope(env->GetIsolate());
     562             :     Local<String> source =
     563             :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     564           6 :                                v8::NewStringType::kNormal)
     565           6 :             .ToLocalChecked();
     566             :     // Trigger GCs so that the newly allocated string moves to old gen.
     567           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     568           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     569           6 :     CHECK(!source->IsExternal());
     570           6 :     CHECK(!source->IsExternalOneByte());
     571           6 :     String::Encoding encoding = String::UNKNOWN_ENCODING;
     572           6 :     CHECK(!source->GetExternalStringResourceBase(&encoding));
     573           6 :     CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
     574             :     bool success = source->MakeExternal(new TestResource(two_byte_source,
     575          12 :                                                          &dispose_count));
     576           6 :     CHECK(success);
     577           6 :     Local<Script> script = v8_compile(source);
     578          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     579           6 :     CHECK(value->IsNumber());
     580          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     581           6 :     CcTest::CollectAllGarbage();
     582          12 :     CHECK_EQ(0, dispose_count);
     583             :   }
     584           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     585           6 :   CcTest::CollectAllGarbage();
     586           6 :   CHECK_EQ(1, dispose_count);
     587           6 : }
     588             : 
     589             : 
     590       25881 : THREADED_TEST(ScriptMakingExternalOneByteString) {
     591           6 :   int dispose_count = 0;
     592             :   const char* c_source = "1 + 2 * 3";
     593             :   {
     594           6 :     LocalContext env;
     595          12 :     v8::HandleScope scope(env->GetIsolate());
     596           6 :     Local<String> source = v8_str(c_source);
     597             :     // Trigger GCs so that the newly allocated string moves to old gen.
     598           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     599           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     600             :     bool success = source->MakeExternal(
     601          12 :         new TestOneByteResource(i::StrDup(c_source), &dispose_count));
     602           6 :     CHECK(success);
     603           6 :     Local<Script> script = v8_compile(source);
     604          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     605           6 :     CHECK(value->IsNumber());
     606          12 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     607           6 :     CcTest::CollectAllGarbage();
     608          12 :     CHECK_EQ(0, dispose_count);
     609             :   }
     610           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     611           6 :   CcTest::CollectAllGarbage();
     612           6 :   CHECK_EQ(1, dispose_count);
     613           6 : }
     614             : 
     615             : 
     616       25880 : TEST(MakingExternalStringConditions) {
     617           5 :   LocalContext env;
     618          10 :   v8::HandleScope scope(env->GetIsolate());
     619             : 
     620             :   // Free some space in the new space so that we can check freshness.
     621           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     622           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     623             : 
     624           5 :   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
     625             :   Local<String> local_string =
     626             :       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
     627           5 :                              v8::NewStringType::kNormal)
     628           5 :           .ToLocalChecked();
     629             :   i::DeleteArray(two_byte_string);
     630             : 
     631             :   // We should refuse to externalize new space strings.
     632           5 :   CHECK(!local_string->CanMakeExternal());
     633             :   // Trigger GCs so that the newly allocated string moves to old gen.
     634           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     635           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     636             :   // Old space strings should be accepted.
     637          10 :   CHECK(local_string->CanMakeExternal());
     638           5 : }
     639             : 
     640             : 
     641       25880 : TEST(MakingExternalOneByteStringConditions) {
     642           5 :   LocalContext env;
     643          10 :   v8::HandleScope scope(env->GetIsolate());
     644             : 
     645             :   // Free some space in the new space so that we can check freshness.
     646           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     647           5 :   CcTest::CollectGarbage(i::NEW_SPACE);
     648             : 
     649           5 :   Local<String> local_string = v8_str("s1");
     650             :   // We should refuse to externalize new space strings.
     651           5 :   CHECK(!local_string->CanMakeExternal());
     652             :   // Trigger GCs so that the newly allocated string moves to old gen.
     653           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     654           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     655             :   // Old space strings should be accepted.
     656          10 :   CHECK(local_string->CanMakeExternal());
     657           5 : }
     658             : 
     659             : 
     660       25880 : TEST(MakingExternalUnalignedOneByteString) {
     661           5 :   LocalContext env;
     662          10 :   v8::HandleScope scope(env->GetIsolate());
     663             : 
     664             :   CompileRun("function cons(a, b) { return a + b; }"
     665             :              "function slice(a) { return a.substring(1); }");
     666             :   // Create a cons string that will land in old pointer space.
     667             :   Local<String> cons = Local<String>::Cast(CompileRun(
     668             :       "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
     669             :   // Create a sliced string that will land in old pointer space.
     670             :   Local<String> slice = Local<String>::Cast(CompileRun(
     671             :       "slice('abcdefghijklmnopqrstuvwxyz');"));
     672             : 
     673             :   // Trigger GCs so that the newly allocated string moves to old gen.
     674           5 :   i::heap::SimulateFullSpace(CcTest::heap()->old_space());
     675           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     676           5 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     677             : 
     678             :   // Turn into external string with unaligned resource data.
     679             :   const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
     680             :   bool success = cons->MakeExternal(
     681          10 :       new TestOneByteResource(i::StrDup(c_cons), nullptr, 1));
     682           5 :   CHECK(success);
     683             :   const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
     684             :   success = slice->MakeExternal(
     685          10 :       new TestOneByteResource(i::StrDup(c_slice), nullptr, 1));
     686           5 :   CHECK(success);
     687             : 
     688             :   // Trigger GCs and force evacuation.
     689           5 :   CcTest::CollectAllGarbage();
     690             :   CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask,
     691          10 :                                     i::GarbageCollectionReason::kTesting);
     692           5 : }
     693             : 
     694       25881 : THREADED_TEST(UsingExternalString) {
     695             :   i::Factory* factory = CcTest::i_isolate()->factory();
     696             :   {
     697           6 :     v8::HandleScope scope(CcTest::isolate());
     698           6 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     699             :     Local<String> string =
     700             :         String::NewExternalTwoByte(CcTest::isolate(),
     701          12 :                                    new TestResource(two_byte_string))
     702           6 :             .ToLocalChecked();
     703           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     704             :     // Trigger GCs so that the newly allocated string moves to old gen.
     705           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     706           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     707             :     i::Handle<i::String> isymbol =
     708           6 :         factory->InternalizeString(istring);
     709          12 :     CHECK(isymbol->IsInternalizedString());
     710             :   }
     711           6 :   CcTest::CollectAllGarbage();
     712           6 :   CcTest::CollectAllGarbage();
     713           6 : }
     714             : 
     715             : 
     716       25881 : THREADED_TEST(UsingExternalOneByteString) {
     717             :   i::Factory* factory = CcTest::i_isolate()->factory();
     718             :   {
     719           6 :     v8::HandleScope scope(CcTest::isolate());
     720             :     const char* one_byte_string = "test string";
     721             :     Local<String> string =
     722             :         String::NewExternalOneByte(
     723             :             CcTest::isolate(),
     724          12 :             new TestOneByteResource(i::StrDup(one_byte_string)))
     725           6 :             .ToLocalChecked();
     726           6 :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     727             :     // Trigger GCs so that the newly allocated string moves to old gen.
     728           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
     729           6 :     CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
     730             :     i::Handle<i::String> isymbol =
     731           6 :         factory->InternalizeString(istring);
     732          12 :     CHECK(isymbol->IsInternalizedString());
     733             :   }
     734           6 :   CcTest::CollectAllGarbage();
     735           6 :   CcTest::CollectAllGarbage();
     736           6 : }
     737             : 
     738             : 
     739           6 : class RandomLengthResource : public v8::String::ExternalStringResource {
     740             :  public:
     741           6 :   explicit RandomLengthResource(int length) : length_(length) {}
     742           6 :   const uint16_t* data() const override { return string_; }
     743           6 :   size_t length() const override { return length_; }
     744             : 
     745             :  private:
     746             :   uint16_t string_[10];
     747             :   int length_;
     748             : };
     749             : 
     750             : 
     751          16 : class RandomLengthOneByteResource
     752             :     : public v8::String::ExternalOneByteStringResource {
     753             :  public:
     754          11 :   explicit RandomLengthOneByteResource(int length) : length_(length) {}
     755          16 :   const char* data() const override { return string_; }
     756          26 :   size_t length() const override { return length_; }
     757             : 
     758             :  private:
     759             :   char string_[10];
     760             :   int length_;
     761             : };
     762             : 
     763             : 
     764       25881 : THREADED_TEST(NewExternalForVeryLongString) {
     765           6 :   auto isolate = CcTest::isolate();
     766             :   {
     767           6 :     v8::HandleScope scope(isolate);
     768          12 :     v8::TryCatch try_catch(isolate);
     769             :     RandomLengthOneByteResource r(1 << 30);
     770             :     v8::MaybeLocal<v8::String> maybe_str =
     771           6 :         v8::String::NewExternalOneByte(isolate, &r);
     772           6 :     CHECK(maybe_str.IsEmpty());
     773          12 :     CHECK(!try_catch.HasCaught());
     774             :   }
     775             : 
     776             :   {
     777           6 :     v8::HandleScope scope(isolate);
     778          12 :     v8::TryCatch try_catch(isolate);
     779             :     RandomLengthResource r(1 << 30);
     780             :     v8::MaybeLocal<v8::String> maybe_str =
     781           6 :         v8::String::NewExternalTwoByte(isolate, &r);
     782           6 :     CHECK(maybe_str.IsEmpty());
     783          12 :     CHECK(!try_catch.HasCaught());
     784             :   }
     785           6 : }
     786             : 
     787       25880 : TEST(ScavengeExternalString) {
     788             :   ManualGCScope manual_gc_scope;
     789           5 :   i::FLAG_stress_compaction = false;
     790           5 :   i::FLAG_gc_global = false;
     791           5 :   int dispose_count = 0;
     792             :   bool in_young_generation = false;
     793             :   {
     794           5 :     v8::HandleScope scope(CcTest::isolate());
     795           5 :     uint16_t* two_byte_string = AsciiToTwoByteString("test string");
     796             :     Local<String> string =
     797             :         String::NewExternalTwoByte(
     798             :             CcTest::isolate(),
     799          10 :             new TestResource(two_byte_string, &dispose_count))
     800           5 :             .ToLocalChecked();
     801             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     802           5 :     CcTest::CollectGarbage(i::NEW_SPACE);
     803             :     in_young_generation = i::Heap::InYoungGeneration(*istring);
     804          10 :     CHECK_IMPLIES(!in_young_generation,
     805             :                   CcTest::heap()->old_space()->Contains(*istring));
     806           5 :     CHECK_EQ(0, dispose_count);
     807             :   }
     808           5 :   CcTest::CollectGarbage(in_young_generation ? i::NEW_SPACE : i::OLD_SPACE);
     809           5 :   CHECK_EQ(1, dispose_count);
     810           5 : }
     811             : 
     812       25880 : TEST(ScavengeExternalOneByteString) {
     813             :   ManualGCScope manual_gc_scope;
     814           5 :   i::FLAG_stress_compaction = false;
     815           5 :   i::FLAG_gc_global = false;
     816           5 :   int dispose_count = 0;
     817             :   bool in_young_generation = false;
     818             :   {
     819           5 :     v8::HandleScope scope(CcTest::isolate());
     820             :     const char* one_byte_string = "test string";
     821             :     Local<String> string =
     822             :         String::NewExternalOneByte(
     823             :             CcTest::isolate(),
     824          10 :             new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
     825           5 :             .ToLocalChecked();
     826             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
     827           5 :     CcTest::CollectGarbage(i::NEW_SPACE);
     828             :     in_young_generation = i::Heap::InYoungGeneration(*istring);
     829          10 :     CHECK_IMPLIES(!in_young_generation,
     830             :                   CcTest::heap()->old_space()->Contains(*istring));
     831           5 :     CHECK_EQ(0, dispose_count);
     832             :   }
     833           5 :   CcTest::CollectGarbage(in_young_generation ? i::NEW_SPACE : i::OLD_SPACE);
     834           5 :   CHECK_EQ(1, dispose_count);
     835           5 : }
     836             : 
     837             : 
     838          10 : class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
     839             :  public:
     840             :   // Only used by non-threaded tests, so it can use static fields.
     841             :   static int dispose_calls;
     842             :   static int dispose_count;
     843             : 
     844             :   TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
     845          10 :       : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
     846             : 
     847          10 :   void Dispose() override {
     848          10 :     ++dispose_calls;
     849          10 :     if (dispose_) delete this;
     850          10 :   }
     851             :  private:
     852             :   bool dispose_;
     853             : };
     854             : 
     855             : 
     856             : int TestOneByteResourceWithDisposeControl::dispose_count = 0;
     857             : int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     858             : 
     859             : 
     860       25880 : TEST(ExternalStringWithDisposeHandling) {
     861             :   const char* c_source = "1 + 2 * 3";
     862             : 
     863             :   // Use a stack allocated external string resource allocated object.
     864           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     865           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     866           5 :   TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
     867             :   {
     868           5 :     LocalContext env;
     869          10 :     v8::HandleScope scope(env->GetIsolate());
     870             :     Local<String> source =
     871           5 :         String::NewExternalOneByte(env->GetIsolate(), &res_stack)
     872          10 :             .ToLocalChecked();
     873           5 :     Local<Script> script = v8_compile(source);
     874          10 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     875           5 :     CHECK(value->IsNumber());
     876          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     877           5 :     CcTest::CollectAllAvailableGarbage();
     878          10 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     879             :   }
     880           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     881           5 :   CcTest::CollectAllAvailableGarbage();
     882           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     883           5 :   CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     884             : 
     885             :   // Use a heap allocated external string resource allocated object.
     886           5 :   TestOneByteResourceWithDisposeControl::dispose_count = 0;
     887           5 :   TestOneByteResourceWithDisposeControl::dispose_calls = 0;
     888             :   TestOneByteResource* res_heap =
     889           5 :       new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
     890             :   {
     891           5 :     LocalContext env;
     892          10 :     v8::HandleScope scope(env->GetIsolate());
     893             :     Local<String> source =
     894           5 :         String::NewExternalOneByte(env->GetIsolate(), res_heap)
     895          10 :             .ToLocalChecked();
     896           5 :     Local<Script> script = v8_compile(source);
     897          10 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     898           5 :     CHECK(value->IsNumber());
     899          10 :     CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
     900           5 :     CcTest::CollectAllAvailableGarbage();
     901          10 :     CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
     902             :   }
     903           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
     904           5 :   CcTest::CollectAllAvailableGarbage();
     905           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
     906           5 :   CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
     907           5 : }
     908             : 
     909             : 
     910       25881 : THREADED_TEST(StringConcat) {
     911             :   {
     912           6 :     LocalContext env;
     913           6 :     v8::Isolate* isolate = env->GetIsolate();
     914          12 :     v8::HandleScope scope(isolate);
     915             :     const char* one_byte_string_1 = "function a_times_t";
     916             :     const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
     917             :     const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
     918             :     const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
     919             :     const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     920             :     const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
     921             :     const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
     922           6 :     Local<String> left = v8_str(one_byte_string_1);
     923             : 
     924           6 :     uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
     925             :     Local<String> right =
     926             :         String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     927           6 :                                v8::NewStringType::kNormal)
     928          12 :             .ToLocalChecked();
     929             :     i::DeleteArray(two_byte_source);
     930             : 
     931           6 :     Local<String> source = String::Concat(isolate, left, right);
     932             :     right = String::NewExternalOneByte(
     933             :                 env->GetIsolate(),
     934          12 :                 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
     935          12 :                 .ToLocalChecked();
     936           6 :     source = String::Concat(isolate, source, right);
     937             :     right = String::NewExternalTwoByte(
     938             :                 env->GetIsolate(),
     939          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
     940          12 :                 .ToLocalChecked();
     941           6 :     source = String::Concat(isolate, source, right);
     942           6 :     right = v8_str(one_byte_string_2);
     943           6 :     source = String::Concat(isolate, source, right);
     944             : 
     945           6 :     two_byte_source = AsciiToTwoByteString(two_byte_string_2);
     946             :     right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
     947           6 :                                    v8::NewStringType::kNormal)
     948          12 :                 .ToLocalChecked();
     949             :     i::DeleteArray(two_byte_source);
     950             : 
     951           6 :     source = String::Concat(isolate, source, right);
     952             :     right = String::NewExternalTwoByte(
     953             :                 env->GetIsolate(),
     954          12 :                 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
     955          12 :                 .ToLocalChecked();
     956           6 :     source = String::Concat(isolate, source, right);
     957           6 :     Local<Script> script = v8_compile(source);
     958          12 :     Local<Value> value = script->Run(env.local()).ToLocalChecked();
     959           6 :     CHECK(value->IsNumber());
     960          18 :     CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
     961             :   }
     962           6 :   CcTest::i_isolate()->compilation_cache()->Clear();
     963           6 :   CcTest::CollectAllGarbage();
     964           6 :   CcTest::CollectAllGarbage();
     965           6 : }
     966             : 
     967             : 
     968       25881 : THREADED_TEST(GlobalProperties) {
     969           6 :   LocalContext env;
     970          12 :   v8::HandleScope scope(env->GetIsolate());
     971           6 :   v8::Local<v8::Object> global = env->Global();
     972          18 :   CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
     973          18 :   Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
     974          18 :   CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
     975           6 : }
     976             : 
     977             : 
     978        1980 : static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
     979             :                                  i::Address callback) {
     980         660 :   ApiTestFuzzer::Fuzz();
     981         660 :   CheckReturnValue(info, callback);
     982         660 :   info.GetReturnValue().Set(v8_str("bad value"));
     983         660 :   info.GetReturnValue().Set(v8_num(102));
     984         660 : }
     985             : 
     986             : 
     987         330 : static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
     988         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
     989             : }
     990             : 
     991             : 
     992         330 : static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
     993         330 :   return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
     994             : }
     995             : 
     996          22 : static void construct_callback(
     997         154 :     const v8::FunctionCallbackInfo<Value>& info) {
     998          22 :   ApiTestFuzzer::Fuzz();
     999          22 :   CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
    1000          88 :   CHECK(
    1001             :       info.This()
    1002             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
    1003             :           .FromJust());
    1004          88 :   CHECK(
    1005             :       info.This()
    1006             :           ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
    1007             :           .FromJust());
    1008          22 :   info.GetReturnValue().Set(v8_str("bad value"));
    1009             :   info.GetReturnValue().Set(info.This());
    1010          22 : }
    1011             : 
    1012             : 
    1013         330 : static void Return239Callback(
    1014             :     Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
    1015         330 :   ApiTestFuzzer::Fuzz();
    1016         330 :   CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
    1017         330 :   info.GetReturnValue().Set(v8_str("bad value"));
    1018         330 :   info.GetReturnValue().Set(v8_num(239));
    1019         330 : }
    1020             : 
    1021             : 
    1022             : template<typename Handler>
    1023          11 : static void TestFunctionTemplateInitializer(Handler handler,
    1024             :                                             Handler handler_2) {
    1025             :   // Test constructor calls.
    1026             :   {
    1027          11 :     LocalContext env;
    1028          11 :     v8::Isolate* isolate = env->GetIsolate();
    1029          22 :     v8::HandleScope scope(isolate);
    1030             : 
    1031             :     Local<v8::FunctionTemplate> fun_templ =
    1032          11 :         v8::FunctionTemplate::New(isolate, handler);
    1033          22 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1034          55 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1035          11 :     Local<Script> script = v8_compile("obj()");
    1036         341 :     for (int i = 0; i < 30; i++) {
    1037         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1038          11 :     }
    1039             :   }
    1040             :   // Use SetCallHandler to initialize a function template, should work like
    1041             :   // the previous one.
    1042             :   {
    1043          11 :     LocalContext env;
    1044          11 :     v8::Isolate* isolate = env->GetIsolate();
    1045          22 :     v8::HandleScope scope(isolate);
    1046             : 
    1047          11 :     Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
    1048          11 :     fun_templ->SetCallHandler(handler_2);
    1049          11 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1050          55 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1051          11 :     Local<Script> script = v8_compile("obj()");
    1052         341 :     for (int i = 0; i < 30; i++) {
    1053         330 :       CHECK_EQ(102, v8_run_int32value(script));
    1054          11 :     }
    1055             :   }
    1056          11 : }
    1057             : 
    1058             : 
    1059             : template<typename Constructor, typename Accessor>
    1060          11 : static void TestFunctionTemplateAccessor(Constructor constructor,
    1061             :                                          Accessor accessor) {
    1062          11 :   LocalContext env;
    1063          22 :   v8::HandleScope scope(env->GetIsolate());
    1064             : 
    1065             :   Local<v8::FunctionTemplate> fun_templ =
    1066          11 :       v8::FunctionTemplate::New(env->GetIsolate(), constructor);
    1067          11 :   fun_templ->SetClassName(v8_str("funky"));
    1068          22 :   fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
    1069          11 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1070          55 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1071             :   Local<Value> result =
    1072          33 :       v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
    1073          33 :   CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
    1074             :   CompileRun("var obj_instance = new obj();");
    1075             :   Local<Script> script;
    1076          11 :   script = v8_compile("obj_instance.x");
    1077         341 :   for (int i = 0; i < 30; i++) {
    1078         330 :     CHECK_EQ(1, v8_run_int32value(script));
    1079             :   }
    1080          11 :   script = v8_compile("obj_instance.m");
    1081         341 :   for (int i = 0; i < 30; i++) {
    1082         330 :     CHECK_EQ(239, v8_run_int32value(script));
    1083          11 :   }
    1084          11 : }
    1085             : 
    1086             : 
    1087       51766 : THREADED_PROFILED_TEST(FunctionTemplate) {
    1088          11 :   TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
    1089          11 :   TestFunctionTemplateAccessor(construct_callback, Return239Callback);
    1090          11 : }
    1091             : 
    1092          18 : static void FunctionCallbackForProxyTest(
    1093          36 :     const v8::FunctionCallbackInfo<Value>& info) {
    1094             :   info.GetReturnValue().Set(info.This());
    1095          18 : }
    1096             : 
    1097       25881 : THREADED_TEST(FunctionTemplateWithProxy) {
    1098           6 :   LocalContext env;
    1099           6 :   v8::Isolate* isolate = env->GetIsolate();
    1100          12 :   v8::HandleScope scope(isolate);
    1101             : 
    1102             :   v8::Local<v8::FunctionTemplate> function_template =
    1103           6 :       v8::FunctionTemplate::New(isolate, FunctionCallbackForProxyTest);
    1104             :   v8::Local<v8::Function> function =
    1105          12 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1106          30 :   CHECK((*env)->Global()->Set(env.local(), v8_str("f"), function).FromJust());
    1107             :   v8::Local<v8::Value> proxy =
    1108             :       CompileRun("var proxy = new Proxy({}, {}); proxy");
    1109           6 :   CHECK(proxy->IsProxy());
    1110             : 
    1111             :   v8::Local<v8::Value> result = CompileRun("f(proxy)");
    1112          18 :   CHECK(result->Equals(env.local(), (*env)->Global()).FromJust());
    1113             : 
    1114             :   result = CompileRun("f.call(proxy)");
    1115          12 :   CHECK(result->Equals(env.local(), proxy).FromJust());
    1116             : 
    1117             :   result = CompileRun("Reflect.apply(f, proxy, [1])");
    1118          18 :   CHECK(result->Equals(env.local(), proxy).FromJust());
    1119           6 : }
    1120             : 
    1121        1980 : static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    1122         660 :   ApiTestFuzzer::Fuzz();
    1123         660 :   CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
    1124         660 :   info.GetReturnValue().Set(v8_num(51423 + info.Length()));
    1125         660 : }
    1126             : 
    1127             : 
    1128             : template<typename Callback>
    1129          11 : static void TestSimpleCallback(Callback callback) {
    1130          11 :   LocalContext env;
    1131          11 :   v8::Isolate* isolate = env->GetIsolate();
    1132          22 :   v8::HandleScope scope(isolate);
    1133             : 
    1134             :   v8::Local<v8::ObjectTemplate> object_template =
    1135          11 :       v8::ObjectTemplate::New(isolate);
    1136          22 :   object_template->Set(isolate, "callback",
    1137             :                        v8::FunctionTemplate::New(isolate, callback));
    1138             :   v8::Local<v8::Object> object =
    1139          11 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1140          55 :   CHECK((*env)
    1141             :             ->Global()
    1142             :             ->Set(env.local(), v8_str("callback_object"), object)
    1143             :             .FromJust());
    1144             :   v8::Local<v8::Script> script;
    1145          11 :   script = v8_compile("callback_object.callback(17)");
    1146         341 :   for (int i = 0; i < 30; i++) {
    1147         330 :     CHECK_EQ(51424, v8_run_int32value(script));
    1148             :   }
    1149          11 :   script = v8_compile("callback_object.callback(17, 24)");
    1150         341 :   for (int i = 0; i < 30; i++) {
    1151         330 :     CHECK_EQ(51425, v8_run_int32value(script));
    1152          11 :   }
    1153          11 : }
    1154             : 
    1155             : 
    1156       51766 : THREADED_PROFILED_TEST(SimpleCallback) {
    1157          11 :   TestSimpleCallback(SimpleCallback);
    1158          11 : }
    1159             : 
    1160             : 
    1161             : template<typename T>
    1162             : void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
    1163             : 
    1164             : // constant return values
    1165             : static int32_t fast_return_value_int32 = 471;
    1166             : static uint32_t fast_return_value_uint32 = 571;
    1167             : static const double kFastReturnValueDouble = 2.7;
    1168             : // variable return values
    1169             : static bool fast_return_value_bool = false;
    1170             : enum ReturnValueOddball {
    1171             :   kNullReturnValue,
    1172             :   kUndefinedReturnValue,
    1173             :   kEmptyStringReturnValue
    1174             : };
    1175             : static ReturnValueOddball fast_return_value_void;
    1176             : static bool fast_return_value_object_is_empty = false;
    1177             : 
    1178             : // Helper function to avoid compiler error: insufficient contextual information
    1179             : // to determine type when applying FUNCTION_ADDR to a template function.
    1180             : static i::Address address_of(v8::FunctionCallback callback) {
    1181         396 :   return FUNCTION_ADDR(callback);
    1182             : }
    1183             : 
    1184             : template<>
    1185         165 : void FastReturnValueCallback<int32_t>(
    1186         165 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1187         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
    1188         165 :   info.GetReturnValue().Set(fast_return_value_int32);
    1189         165 : }
    1190             : 
    1191             : template<>
    1192         165 : void FastReturnValueCallback<uint32_t>(
    1193         165 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1194         165 :   CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
    1195         165 :   info.GetReturnValue().Set(fast_return_value_uint32);
    1196         165 : }
    1197             : 
    1198             : template<>
    1199          11 : void FastReturnValueCallback<double>(
    1200          11 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1201          11 :   CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
    1202             :   info.GetReturnValue().Set(kFastReturnValueDouble);
    1203          11 : }
    1204             : 
    1205             : template<>
    1206          22 : void FastReturnValueCallback<bool>(
    1207          22 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1208          22 :   CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
    1209          22 :   info.GetReturnValue().Set(fast_return_value_bool);
    1210          22 : }
    1211             : 
    1212             : template<>
    1213          33 : void FastReturnValueCallback<void>(
    1214          33 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1215          33 :   CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
    1216          33 :   switch (fast_return_value_void) {
    1217             :     case kNullReturnValue:
    1218             :       info.GetReturnValue().SetNull();
    1219          11 :       break;
    1220             :     case kUndefinedReturnValue:
    1221             :       info.GetReturnValue().SetUndefined();
    1222          11 :       break;
    1223             :     case kEmptyStringReturnValue:
    1224             :       info.GetReturnValue().SetEmptyString();
    1225          11 :       break;
    1226             :   }
    1227          33 : }
    1228             : 
    1229             : template<>
    1230          22 : void FastReturnValueCallback<Object>(
    1231          33 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
    1232             :   v8::Local<v8::Object> object;
    1233          22 :   if (!fast_return_value_object_is_empty) {
    1234          11 :     object = Object::New(info.GetIsolate());
    1235             :   }
    1236             :   info.GetReturnValue().Set(object);
    1237          22 : }
    1238             : 
    1239             : template <typename T>
    1240         418 : Local<Value> TestFastReturnValues() {
    1241         418 :   LocalContext env;
    1242         418 :   v8::Isolate* isolate = env->GetIsolate();
    1243         418 :   v8::EscapableHandleScope scope(isolate);
    1244             :   v8::Local<v8::ObjectTemplate> object_template =
    1245         418 :       v8::ObjectTemplate::New(isolate);
    1246             :   v8::FunctionCallback callback = &FastReturnValueCallback<T>;
    1247             :   object_template->Set(isolate, "callback",
    1248         836 :                        v8::FunctionTemplate::New(isolate, callback));
    1249             :   v8::Local<v8::Object> object =
    1250         418 :       object_template->NewInstance(env.local()).ToLocalChecked();
    1251        2090 :   CHECK((*env)
    1252             :             ->Global()
    1253             :             ->Set(env.local(), v8_str("callback_object"), object)
    1254             :             .FromJust());
    1255         418 :   return scope.Escape(CompileRun("callback_object.callback()"));
    1256             : }
    1257             : 
    1258             : 
    1259       51766 : THREADED_PROFILED_TEST(FastReturnValues) {
    1260          11 :   LocalContext env;
    1261          11 :   v8::Isolate* isolate = env->GetIsolate();
    1262          22 :   v8::HandleScope scope(isolate);
    1263             :   v8::Local<v8::Value> value;
    1264             :   // check int32_t and uint32_t
    1265             :   int32_t int_values[] = {
    1266             :       0, 234, -723,
    1267             :       i::Smi::kMinValue, i::Smi::kMaxValue
    1268          11 :   };
    1269          66 :   for (size_t i = 0; i < arraysize(int_values); i++) {
    1270         165 :     for (int modifier = -1; modifier <= 1; modifier++) {
    1271         165 :       int int_value = v8::base::AddWithWraparound(int_values[i], modifier);
    1272             :       // check int32_t
    1273         165 :       fast_return_value_int32 = int_value;
    1274         165 :       value = TestFastReturnValues<int32_t>();
    1275         165 :       CHECK(value->IsInt32());
    1276         330 :       CHECK_EQ(fast_return_value_int32,
    1277             :                value->Int32Value(env.local()).FromJust());
    1278             :       // check uint32_t
    1279         165 :       fast_return_value_uint32 = static_cast<uint32_t>(int_value);
    1280         165 :       value = TestFastReturnValues<uint32_t>();
    1281         165 :       CHECK(value->IsUint32());
    1282         330 :       CHECK_EQ(fast_return_value_uint32,
    1283             :                value->Uint32Value(env.local()).FromJust());
    1284             :     }
    1285             :   }
    1286             :   // check double
    1287          11 :   value = TestFastReturnValues<double>();
    1288          11 :   CHECK(value->IsNumber());
    1289          22 :   CHECK_EQ(kFastReturnValueDouble,
    1290             :            value->ToNumber(env.local()).ToLocalChecked()->Value());
    1291             :   // check bool values
    1292          22 :   for (int i = 0; i < 2; i++) {
    1293          22 :     fast_return_value_bool = i == 0;
    1294          22 :     value = TestFastReturnValues<bool>();
    1295          22 :     CHECK(value->IsBoolean());
    1296          22 :     CHECK_EQ(fast_return_value_bool, value->BooleanValue(isolate));
    1297             :   }
    1298             :   // check oddballs
    1299             :   ReturnValueOddball oddballs[] = {
    1300             :       kNullReturnValue,
    1301             :       kUndefinedReturnValue,
    1302             :       kEmptyStringReturnValue
    1303          11 :   };
    1304          44 :   for (size_t i = 0; i < arraysize(oddballs); i++) {
    1305          33 :     fast_return_value_void = oddballs[i];
    1306          33 :     value = TestFastReturnValues<void>();
    1307          33 :     switch (fast_return_value_void) {
    1308             :       case kNullReturnValue:
    1309          11 :         CHECK(value->IsNull());
    1310             :         break;
    1311             :       case kUndefinedReturnValue:
    1312          11 :         CHECK(value->IsUndefined());
    1313             :         break;
    1314             :       case kEmptyStringReturnValue:
    1315          11 :         CHECK(value->IsString());
    1316          11 :         CHECK_EQ(0, v8::String::Cast(*value)->Length());
    1317             :         break;
    1318             :     }
    1319             :   }
    1320             :   // check handles
    1321          11 :   fast_return_value_object_is_empty = false;
    1322          11 :   value = TestFastReturnValues<Object>();
    1323          11 :   CHECK(value->IsObject());
    1324          11 :   fast_return_value_object_is_empty = true;
    1325          11 :   value = TestFastReturnValues<Object>();
    1326          22 :   CHECK(value->IsUndefined());
    1327          11 : }
    1328             : 
    1329             : 
    1330       25881 : THREADED_TEST(FunctionTemplateSetLength) {
    1331           6 :   LocalContext env;
    1332           6 :   v8::Isolate* isolate = env->GetIsolate();
    1333          12 :   v8::HandleScope scope(isolate);
    1334             :   {
    1335             :     Local<v8::FunctionTemplate> fun_templ =
    1336             :         v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
    1337           6 :                                   Local<v8::Signature>(), 23);
    1338          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1339          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1340           6 :     Local<Script> script = v8_compile("obj.length");
    1341           6 :     CHECK_EQ(23, v8_run_int32value(script));
    1342             :   }
    1343             :   {
    1344             :     Local<v8::FunctionTemplate> fun_templ =
    1345           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1346           6 :     fun_templ->SetLength(22);
    1347           6 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1348          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1349           6 :     Local<Script> script = v8_compile("obj.length");
    1350           6 :     CHECK_EQ(22, v8_run_int32value(script));
    1351             :   }
    1352             :   {
    1353             :     // Without setting length it defaults to 0.
    1354             :     Local<v8::FunctionTemplate> fun_templ =
    1355           6 :         v8::FunctionTemplate::New(isolate, handle_callback);
    1356          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
    1357          30 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
    1358           6 :     Local<Script> script = v8_compile("obj.length");
    1359           6 :     CHECK_EQ(0, v8_run_int32value(script));
    1360           6 :   }
    1361           6 : }
    1362             : 
    1363             : 
    1364             : static void* expected_ptr;
    1365       16848 : static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1366        8424 :   void* ptr = v8::External::Cast(*args.Data())->Value();
    1367        8424 :   CHECK_EQ(expected_ptr, ptr);
    1368             :   args.GetReturnValue().Set(true);
    1369        8424 : }
    1370             : 
    1371             : 
    1372         648 : static void TestExternalPointerWrapping() {
    1373         648 :   LocalContext env;
    1374         648 :   v8::Isolate* isolate = env->GetIsolate();
    1375        1296 :   v8::HandleScope scope(isolate);
    1376             : 
    1377         648 :   v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
    1378             : 
    1379         648 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    1380        4536 :   CHECK(obj->Set(env.local(), v8_str("func"),
    1381             :                  v8::FunctionTemplate::New(isolate, callback, data)
    1382             :                      ->GetFunction(env.local())
    1383             :                      .ToLocalChecked())
    1384             :             .FromJust());
    1385        3240 :   CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
    1386             : 
    1387         648 :   CHECK(CompileRun("function foo() {\n"
    1388             :                    "  for (var i = 0; i < 13; i++) obj.func();\n"
    1389             :                    "}\n"
    1390             :                    "foo(), true")
    1391         648 :             ->BooleanValue(isolate));
    1392         648 : }
    1393             : 
    1394             : 
    1395       25881 : THREADED_TEST(ExternalWrap) {
    1396             :   // Check heap allocated object.
    1397           6 :   int* ptr = new int;
    1398           6 :   expected_ptr = ptr;
    1399           6 :   TestExternalPointerWrapping();
    1400           6 :   delete ptr;
    1401             : 
    1402             :   // Check stack allocated object.
    1403             :   int foo;
    1404           6 :   expected_ptr = &foo;
    1405           6 :   TestExternalPointerWrapping();
    1406             : 
    1407             :   // Check not aligned addresses.
    1408             :   const int n = 100;
    1409           6 :   char* s = new char[n];
    1410         606 :   for (int i = 0; i < n; i++) {
    1411         600 :     expected_ptr = s + i;
    1412         600 :     TestExternalPointerWrapping();
    1413             :   }
    1414             : 
    1415           6 :   delete[] s;
    1416             : 
    1417             :   // Check several invalid addresses.
    1418           6 :   expected_ptr = reinterpret_cast<void*>(1);
    1419           6 :   TestExternalPointerWrapping();
    1420             : 
    1421           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEF);
    1422           6 :   TestExternalPointerWrapping();
    1423             : 
    1424           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEF + 1);
    1425           6 :   TestExternalPointerWrapping();
    1426             : 
    1427             : #if defined(V8_HOST_ARCH_X64)
    1428             :   // Check a value with a leading 1 bit in x64 Smi encoding.
    1429           6 :   expected_ptr = reinterpret_cast<void*>(0x400000000);
    1430           6 :   TestExternalPointerWrapping();
    1431             : 
    1432           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEFDEADBEEF);
    1433           6 :   TestExternalPointerWrapping();
    1434             : 
    1435           6 :   expected_ptr = reinterpret_cast<void*>(0xDEADBEEFDEADBEEF + 1);
    1436           6 :   TestExternalPointerWrapping();
    1437             : #endif
    1438           6 : }
    1439             : 
    1440             : 
    1441       25881 : THREADED_TEST(FindInstanceInPrototypeChain) {
    1442           6 :   LocalContext env;
    1443           6 :   v8::Isolate* isolate = env->GetIsolate();
    1444          12 :   v8::HandleScope scope(isolate);
    1445             : 
    1446           6 :   Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
    1447           6 :   Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
    1448           6 :   Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
    1449           6 :   derived->Inherit(base);
    1450             : 
    1451             :   Local<v8::Function> base_function =
    1452          12 :       base->GetFunction(env.local()).ToLocalChecked();
    1453             :   Local<v8::Function> derived_function =
    1454           6 :       derived->GetFunction(env.local()).ToLocalChecked();
    1455             :   Local<v8::Function> other_function =
    1456          12 :       other->GetFunction(env.local()).ToLocalChecked();
    1457             : 
    1458             :   Local<v8::Object> base_instance =
    1459           6 :       base_function->NewInstance(env.local()).ToLocalChecked();
    1460             :   Local<v8::Object> derived_instance =
    1461           6 :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1462             :   Local<v8::Object> derived_instance2 =
    1463           6 :       derived_function->NewInstance(env.local()).ToLocalChecked();
    1464             :   Local<v8::Object> other_instance =
    1465           6 :       other_function->NewInstance(env.local()).ToLocalChecked();
    1466          18 :   CHECK(
    1467             :       derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
    1468             :           .FromJust());
    1469          18 :   CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
    1470             :             .FromJust());
    1471             : 
    1472             :   // base_instance is only an instance of base.
    1473          18 :   CHECK(base_instance->Equals(env.local(),
    1474             :                               base_instance->FindInstanceInPrototypeChain(base))
    1475             :             .FromJust());
    1476          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
    1477          12 :   CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1478             : 
    1479             :   // derived_instance is an instance of base and derived.
    1480          18 :   CHECK(derived_instance->Equals(env.local(),
    1481             :                                  derived_instance->FindInstanceInPrototypeChain(
    1482             :                                      base))
    1483             :             .FromJust());
    1484          18 :   CHECK(derived_instance->Equals(env.local(),
    1485             :                                  derived_instance->FindInstanceInPrototypeChain(
    1486             :                                      derived))
    1487             :             .FromJust());
    1488          12 :   CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
    1489             : 
    1490             :   // other_instance is an instance of other and its immediate
    1491             :   // prototype derived_instance2 is an instance of base and derived.
    1492             :   // Note, derived_instance is an instance of base and derived too,
    1493             :   // but it comes after derived_instance2 in the prototype chain of
    1494             :   // other_instance.
    1495          18 :   CHECK(derived_instance2->Equals(
    1496             :                              env.local(),
    1497             :                              other_instance->FindInstanceInPrototypeChain(base))
    1498             :             .FromJust());
    1499          18 :   CHECK(derived_instance2->Equals(env.local(),
    1500             :                                   other_instance->FindInstanceInPrototypeChain(
    1501             :                                       derived))
    1502             :             .FromJust());
    1503          18 :   CHECK(other_instance->Equals(
    1504             :                           env.local(),
    1505             :                           other_instance->FindInstanceInPrototypeChain(other))
    1506           6 :             .FromJust());
    1507           6 : }
    1508             : 
    1509             : 
    1510       25881 : THREADED_TEST(TinyInteger) {
    1511           6 :   LocalContext env;
    1512           6 :   v8::Isolate* isolate = env->GetIsolate();
    1513          12 :   v8::HandleScope scope(isolate);
    1514             : 
    1515             :   int32_t value = 239;
    1516           6 :   Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1517          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1518           6 : }
    1519             : 
    1520             : 
    1521       25881 : THREADED_TEST(BigSmiInteger) {
    1522           6 :   LocalContext env;
    1523          12 :   v8::HandleScope scope(env->GetIsolate());
    1524           6 :   v8::Isolate* isolate = CcTest::isolate();
    1525             : 
    1526             :   int32_t value = i::Smi::kMaxValue;
    1527             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1528             :   if (i::SmiValuesAre31Bits()) {
    1529             :     CHECK(i::Smi::IsValid(value));
    1530             :     CHECK(!i::Smi::IsValid(value + 1));
    1531             : 
    1532             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1533             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1534           6 :   }
    1535           6 : }
    1536             : 
    1537             : 
    1538       25881 : THREADED_TEST(BigInteger) {
    1539           6 :   LocalContext env;
    1540          12 :   v8::HandleScope scope(env->GetIsolate());
    1541           6 :   v8::Isolate* isolate = CcTest::isolate();
    1542             : 
    1543             :   // We cannot add one to a Smi::kMaxValue without wrapping.
    1544             :   if (i::SmiValuesAre31Bits()) {
    1545             :     // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
    1546             :     // The code will not be run in that case, due to the "if" guard.
    1547             :     int32_t value =
    1548             :         static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
    1549             :     CHECK_GT(value, i::Smi::kMaxValue);
    1550             :     CHECK(!i::Smi::IsValid(value));
    1551             : 
    1552             :     Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
    1553             :     CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1554           6 :   }
    1555           6 : }
    1556             : 
    1557             : 
    1558       25881 : THREADED_TEST(TinyUnsignedInteger) {
    1559           6 :   LocalContext env;
    1560          12 :   v8::HandleScope scope(env->GetIsolate());
    1561           6 :   v8::Isolate* isolate = CcTest::isolate();
    1562             : 
    1563             :   uint32_t value = 239;
    1564             : 
    1565           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1566          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1567           6 : }
    1568             : 
    1569             : 
    1570       25881 : THREADED_TEST(BigUnsignedSmiInteger) {
    1571           6 :   LocalContext env;
    1572          12 :   v8::HandleScope scope(env->GetIsolate());
    1573           6 :   v8::Isolate* isolate = CcTest::isolate();
    1574             : 
    1575             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
    1576             :   CHECK(i::Smi::IsValid(value));
    1577             :   CHECK(!i::Smi::IsValid(value + 1));
    1578             : 
    1579           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1580          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1581           6 : }
    1582             : 
    1583             : 
    1584       25881 : THREADED_TEST(BigUnsignedInteger) {
    1585           6 :   LocalContext env;
    1586          12 :   v8::HandleScope scope(env->GetIsolate());
    1587           6 :   v8::Isolate* isolate = CcTest::isolate();
    1588             : 
    1589             :   uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
    1590             :   CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
    1591             :   CHECK(!i::Smi::IsValid(value));
    1592             : 
    1593           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1594          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1595           6 : }
    1596             : 
    1597             : 
    1598       25881 : THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
    1599           6 :   LocalContext env;
    1600          12 :   v8::HandleScope scope(env->GetIsolate());
    1601           6 :   v8::Isolate* isolate = CcTest::isolate();
    1602             : 
    1603             :   uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
    1604             :   uint32_t value = INT32_MAX_AS_UINT + 1;
    1605             :   CHECK(value > INT32_MAX_AS_UINT);  // No overflow.
    1606             : 
    1607           6 :   Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
    1608          12 :   CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
    1609           6 : }
    1610             : 
    1611             : 
    1612       25881 : THREADED_TEST(IsNativeError) {
    1613           6 :   LocalContext env;
    1614          12 :   v8::HandleScope scope(env->GetIsolate());
    1615             :   v8::Local<Value> syntax_error = CompileRun(
    1616             :       "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
    1617           6 :   CHECK(syntax_error->IsNativeError());
    1618             :   v8::Local<Value> not_error = CompileRun("{a:42}");
    1619           6 :   CHECK(!not_error->IsNativeError());
    1620             :   v8::Local<Value> not_object = CompileRun("42");
    1621          12 :   CHECK(!not_object->IsNativeError());
    1622           6 : }
    1623             : 
    1624             : 
    1625       25881 : THREADED_TEST(IsGeneratorFunctionOrObject) {
    1626           6 :   LocalContext env;
    1627          12 :   v8::HandleScope scope(env->GetIsolate());
    1628             : 
    1629             :   CompileRun("function *gen() { yield 1; }\nfunction func() {}");
    1630             :   v8::Local<Value> gen = CompileRun("gen");
    1631             :   v8::Local<Value> genObj = CompileRun("gen()");
    1632             :   v8::Local<Value> object = CompileRun("{a:42}");
    1633             :   v8::Local<Value> func = CompileRun("func");
    1634             : 
    1635           6 :   CHECK(gen->IsGeneratorFunction());
    1636           6 :   CHECK(gen->IsFunction());
    1637           6 :   CHECK(!gen->IsGeneratorObject());
    1638             : 
    1639           6 :   CHECK(!genObj->IsGeneratorFunction());
    1640           6 :   CHECK(!genObj->IsFunction());
    1641           6 :   CHECK(genObj->IsGeneratorObject());
    1642             : 
    1643           6 :   CHECK(!object->IsGeneratorFunction());
    1644           6 :   CHECK(!object->IsFunction());
    1645           6 :   CHECK(!object->IsGeneratorObject());
    1646             : 
    1647           6 :   CHECK(!func->IsGeneratorFunction());
    1648           6 :   CHECK(func->IsFunction());
    1649          12 :   CHECK(!func->IsGeneratorObject());
    1650           6 : }
    1651             : 
    1652       25881 : THREADED_TEST(IsAsyncFunction) {
    1653           6 :   LocalContext env;
    1654           6 :   v8::Isolate* isolate = env->GetIsolate();
    1655          12 :   v8::HandleScope scope(isolate);
    1656             : 
    1657             :   CompileRun("async function foo() {}");
    1658             :   v8::Local<Value> foo = CompileRun("foo");
    1659             : 
    1660           6 :   CHECK(foo->IsAsyncFunction());
    1661           6 :   CHECK(foo->IsFunction());
    1662           6 :   CHECK(!foo->IsGeneratorFunction());
    1663           6 :   CHECK(!foo->IsGeneratorObject());
    1664             : 
    1665             :   CompileRun("function bar() {}");
    1666             :   v8::Local<Value> bar = CompileRun("bar");
    1667             : 
    1668           6 :   CHECK(!bar->IsAsyncFunction());
    1669          12 :   CHECK(bar->IsFunction());
    1670           6 : }
    1671             : 
    1672       25881 : THREADED_TEST(ArgumentsObject) {
    1673           6 :   LocalContext env;
    1674          12 :   v8::HandleScope scope(env->GetIsolate());
    1675             :   v8::Local<Value> arguments_object =
    1676             :       CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
    1677           6 :   CHECK(arguments_object->IsArgumentsObject());
    1678             :   v8::Local<Value> array = CompileRun("[1,2,3]");
    1679           6 :   CHECK(!array->IsArgumentsObject());
    1680             :   v8::Local<Value> object = CompileRun("{a:42}");
    1681          12 :   CHECK(!object->IsArgumentsObject());
    1682           6 : }
    1683             : 
    1684             : 
    1685       25881 : THREADED_TEST(IsMapOrSet) {
    1686           6 :   LocalContext env;
    1687          12 :   v8::HandleScope scope(env->GetIsolate());
    1688             :   v8::Local<Value> map = CompileRun("new Map()");
    1689             :   v8::Local<Value> set = CompileRun("new Set()");
    1690             :   v8::Local<Value> weak_map = CompileRun("new WeakMap()");
    1691             :   v8::Local<Value> weak_set = CompileRun("new WeakSet()");
    1692           6 :   CHECK(map->IsMap());
    1693           6 :   CHECK(set->IsSet());
    1694           6 :   CHECK(weak_map->IsWeakMap());
    1695           6 :   CHECK(weak_set->IsWeakSet());
    1696             : 
    1697           6 :   CHECK(!map->IsSet());
    1698           6 :   CHECK(!map->IsWeakMap());
    1699           6 :   CHECK(!map->IsWeakSet());
    1700             : 
    1701           6 :   CHECK(!set->IsMap());
    1702           6 :   CHECK(!set->IsWeakMap());
    1703           6 :   CHECK(!set->IsWeakSet());
    1704             : 
    1705           6 :   CHECK(!weak_map->IsMap());
    1706           6 :   CHECK(!weak_map->IsSet());
    1707           6 :   CHECK(!weak_map->IsWeakSet());
    1708             : 
    1709           6 :   CHECK(!weak_set->IsMap());
    1710           6 :   CHECK(!weak_set->IsSet());
    1711           6 :   CHECK(!weak_set->IsWeakMap());
    1712             : 
    1713             :   v8::Local<Value> object = CompileRun("{a:42}");
    1714           6 :   CHECK(!object->IsMap());
    1715           6 :   CHECK(!object->IsSet());
    1716           6 :   CHECK(!object->IsWeakMap());
    1717          12 :   CHECK(!object->IsWeakSet());
    1718           6 : }
    1719             : 
    1720             : 
    1721       25881 : THREADED_TEST(StringObject) {
    1722           6 :   LocalContext env;
    1723          12 :   v8::HandleScope scope(env->GetIsolate());
    1724             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1725           6 :   CHECK(boxed_string->IsStringObject());
    1726             :   v8::Local<Value> unboxed_string = CompileRun("\"test\"");
    1727           6 :   CHECK(!unboxed_string->IsStringObject());
    1728             :   v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
    1729           6 :   CHECK(!boxed_not_string->IsStringObject());
    1730             :   v8::Local<Value> not_object = CompileRun("0");
    1731           6 :   CHECK(!not_object->IsStringObject());
    1732             :   v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
    1733           6 :   CHECK(!as_boxed.IsEmpty());
    1734           6 :   Local<v8::String> the_string = as_boxed->ValueOf();
    1735           6 :   CHECK(!the_string.IsEmpty());
    1736           6 :   ExpectObject("\"test\"", the_string);
    1737             :   v8::Local<v8::Value> new_boxed_string =
    1738           6 :       v8::StringObject::New(CcTest::isolate(), the_string);
    1739           6 :   CHECK(new_boxed_string->IsStringObject());
    1740             :   as_boxed = new_boxed_string.As<v8::StringObject>();
    1741           6 :   the_string = as_boxed->ValueOf();
    1742           6 :   CHECK(!the_string.IsEmpty());
    1743          12 :   ExpectObject("\"test\"", the_string);
    1744           6 : }
    1745             : 
    1746             : 
    1747       25880 : TEST(StringObjectDelete) {
    1748           5 :   LocalContext context;
    1749          10 :   v8::HandleScope scope(context->GetIsolate());
    1750             :   v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
    1751           5 :   CHECK(boxed_string->IsStringObject());
    1752             :   v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
    1753          10 :   CHECK(!str_obj->Delete(context.local(), 2).FromJust());
    1754          15 :   CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
    1755           5 : }
    1756             : 
    1757             : 
    1758       25881 : THREADED_TEST(NumberObject) {
    1759           6 :   LocalContext env;
    1760          12 :   v8::HandleScope scope(env->GetIsolate());
    1761             :   v8::Local<Value> boxed_number = CompileRun("new Number(42)");
    1762           6 :   CHECK(boxed_number->IsNumberObject());
    1763             :   v8::Local<Value> unboxed_number = CompileRun("42");
    1764           6 :   CHECK(!unboxed_number->IsNumberObject());
    1765             :   v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
    1766           6 :   CHECK(!boxed_not_number->IsNumberObject());
    1767             :   v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
    1768           6 :   CHECK(!as_boxed.IsEmpty());
    1769           6 :   double the_number = as_boxed->ValueOf();
    1770           6 :   CHECK_EQ(42.0, the_number);
    1771             :   v8::Local<v8::Value> new_boxed_number =
    1772           6 :       v8::NumberObject::New(env->GetIsolate(), 43);
    1773           6 :   CHECK(new_boxed_number->IsNumberObject());
    1774             :   as_boxed = new_boxed_number.As<v8::NumberObject>();
    1775           6 :   the_number = as_boxed->ValueOf();
    1776          12 :   CHECK_EQ(43.0, the_number);
    1777           6 : }
    1778             : 
    1779       25881 : THREADED_TEST(BigIntObject) {
    1780           6 :   LocalContext env;
    1781           6 :   v8::Isolate* isolate = env->GetIsolate();
    1782          12 :   v8::HandleScope scope(isolate);
    1783           6 :   v8::Local<v8::Context> context(env.local());
    1784             :   v8::Local<Value> boxed_bigint = CompileRun("new Object(42n)");
    1785           6 :   CHECK(!boxed_bigint->IsBigInt());
    1786           6 :   CHECK(boxed_bigint->IsBigIntObject());
    1787             :   v8::Local<Value> unboxed_bigint = CompileRun("42n");
    1788           6 :   CHECK(unboxed_bigint->IsBigInt());
    1789           6 :   CHECK(!unboxed_bigint->IsBigIntObject());
    1790             :   v8::Local<v8::BigIntObject> as_boxed = boxed_bigint.As<v8::BigIntObject>();
    1791           6 :   CHECK(!as_boxed.IsEmpty());
    1792           6 :   v8::Local<v8::BigInt> unpacked = as_boxed->ValueOf();
    1793           6 :   CHECK(!unpacked.IsEmpty());
    1794           6 :   v8::Local<v8::Value> new_boxed_bigint = v8::BigIntObject::New(isolate, 43);
    1795           6 :   CHECK(new_boxed_bigint->IsBigIntObject());
    1796           6 :   v8::Local<v8::Value> new_unboxed_bigint = v8::BigInt::New(isolate, 44);
    1797           6 :   CHECK(new_unboxed_bigint->IsBigInt());
    1798             : 
    1799             :   // Test functionality inherited from v8::Value.
    1800           6 :   CHECK(unboxed_bigint->BooleanValue(isolate));
    1801             :   v8::Local<v8::String> string =
    1802           6 :       unboxed_bigint->ToString(context).ToLocalChecked();
    1803           6 :   CHECK_EQ(0, strcmp("42", *v8::String::Utf8Value(isolate, string)));
    1804             : 
    1805             :   // IntegerValue throws.
    1806          18 :   CHECK(unboxed_bigint->IntegerValue(context).IsNothing());
    1807           6 : }
    1808             : 
    1809       25881 : THREADED_TEST(BooleanObject) {
    1810           6 :   LocalContext env;
    1811          12 :   v8::HandleScope scope(env->GetIsolate());
    1812             :   v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
    1813           6 :   CHECK(boxed_boolean->IsBooleanObject());
    1814             :   v8::Local<Value> unboxed_boolean = CompileRun("true");
    1815           6 :   CHECK(!unboxed_boolean->IsBooleanObject());
    1816             :   v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
    1817           6 :   CHECK(!boxed_not_boolean->IsBooleanObject());
    1818             :   v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
    1819           6 :   CHECK(!as_boxed.IsEmpty());
    1820           6 :   bool the_boolean = as_boxed->ValueOf();
    1821           6 :   CHECK(the_boolean);
    1822             :   v8::Local<v8::Value> boxed_true =
    1823           6 :       v8::BooleanObject::New(env->GetIsolate(), true);
    1824             :   v8::Local<v8::Value> boxed_false =
    1825           6 :       v8::BooleanObject::New(env->GetIsolate(), false);
    1826           6 :   CHECK(boxed_true->IsBooleanObject());
    1827           6 :   CHECK(boxed_false->IsBooleanObject());
    1828             :   as_boxed = boxed_true.As<v8::BooleanObject>();
    1829           6 :   CHECK(as_boxed->ValueOf());
    1830             :   as_boxed = boxed_false.As<v8::BooleanObject>();
    1831          12 :   CHECK(!as_boxed->ValueOf());
    1832           6 : }
    1833             : 
    1834             : 
    1835       25881 : THREADED_TEST(PrimitiveAndWrappedBooleans) {
    1836           6 :   LocalContext env;
    1837           6 :   v8::Isolate* isolate = env->GetIsolate();
    1838          12 :   v8::HandleScope scope(isolate);
    1839             : 
    1840             :   Local<Value> primitive_false = Boolean::New(isolate, false);
    1841           6 :   CHECK(primitive_false->IsBoolean());
    1842           6 :   CHECK(!primitive_false->IsBooleanObject());
    1843           6 :   CHECK(!primitive_false->BooleanValue(isolate));
    1844           6 :   CHECK(!primitive_false->IsTrue());
    1845           6 :   CHECK(primitive_false->IsFalse());
    1846             : 
    1847           6 :   Local<Value> false_value = BooleanObject::New(isolate, false);
    1848           6 :   CHECK(!false_value->IsBoolean());
    1849           6 :   CHECK(false_value->IsBooleanObject());
    1850           6 :   CHECK(false_value->BooleanValue(isolate));
    1851           6 :   CHECK(!false_value->IsTrue());
    1852           6 :   CHECK(!false_value->IsFalse());
    1853             : 
    1854             :   Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
    1855           6 :   CHECK(!false_boolean_object->IsBoolean());
    1856           6 :   CHECK(false_boolean_object->IsBooleanObject());
    1857           6 :   CHECK(false_boolean_object->BooleanValue(isolate));
    1858           6 :   CHECK(!false_boolean_object->ValueOf());
    1859           6 :   CHECK(!false_boolean_object->IsTrue());
    1860           6 :   CHECK(!false_boolean_object->IsFalse());
    1861             : 
    1862             :   Local<Value> primitive_true = Boolean::New(isolate, true);
    1863           6 :   CHECK(primitive_true->IsBoolean());
    1864           6 :   CHECK(!primitive_true->IsBooleanObject());
    1865           6 :   CHECK(primitive_true->BooleanValue(isolate));
    1866           6 :   CHECK(primitive_true->IsTrue());
    1867           6 :   CHECK(!primitive_true->IsFalse());
    1868             : 
    1869           6 :   Local<Value> true_value = BooleanObject::New(isolate, true);
    1870           6 :   CHECK(!true_value->IsBoolean());
    1871           6 :   CHECK(true_value->IsBooleanObject());
    1872           6 :   CHECK(true_value->BooleanValue(isolate));
    1873           6 :   CHECK(!true_value->IsTrue());
    1874           6 :   CHECK(!true_value->IsFalse());
    1875             : 
    1876             :   Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
    1877           6 :   CHECK(!true_boolean_object->IsBoolean());
    1878           6 :   CHECK(true_boolean_object->IsBooleanObject());
    1879           6 :   CHECK(true_boolean_object->BooleanValue(isolate));
    1880           6 :   CHECK(true_boolean_object->ValueOf());
    1881           6 :   CHECK(!true_boolean_object->IsTrue());
    1882          12 :   CHECK(!true_boolean_object->IsFalse());
    1883           6 : }
    1884             : 
    1885             : 
    1886       25881 : THREADED_TEST(Number) {
    1887           6 :   LocalContext env;
    1888          12 :   v8::HandleScope scope(env->GetIsolate());
    1889             :   double PI = 3.1415926;
    1890           6 :   Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
    1891          24 :   CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
    1892           6 : }
    1893             : 
    1894             : 
    1895       25881 : THREADED_TEST(ToNumber) {
    1896           6 :   LocalContext env;
    1897           6 :   v8::Isolate* isolate = CcTest::isolate();
    1898          12 :   v8::HandleScope scope(isolate);
    1899           6 :   Local<String> str = v8_str("3.1415926");
    1900          18 :   CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
    1901             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1902          12 :   CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
    1903             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1904          18 :   CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
    1905           6 : }
    1906             : 
    1907             : 
    1908       25881 : THREADED_TEST(Date) {
    1909           6 :   LocalContext env;
    1910          12 :   v8::HandleScope scope(env->GetIsolate());
    1911             :   double PI = 3.1415926;
    1912           6 :   Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
    1913          12 :   CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
    1914          24 :   CHECK(date.As<v8::Date>()
    1915             :             ->Set(env.local(), v8_str("property"),
    1916             :                   v8::Integer::New(env->GetIsolate(), 42))
    1917             :             .FromJust());
    1918          24 :   CHECK_EQ(42, date.As<v8::Date>()
    1919             :                    ->Get(env.local(), v8_str("property"))
    1920             :                    .ToLocalChecked()
    1921             :                    ->Int32Value(env.local())
    1922           6 :                    .FromJust());
    1923           6 : }
    1924             : 
    1925             : 
    1926       25881 : THREADED_TEST(Boolean) {
    1927           6 :   LocalContext env;
    1928           6 :   v8::Isolate* isolate = env->GetIsolate();
    1929          12 :   v8::HandleScope scope(isolate);
    1930             :   v8::Local<v8::Boolean> t = v8::True(isolate);
    1931           6 :   CHECK(t->Value());
    1932             :   v8::Local<v8::Boolean> f = v8::False(isolate);
    1933           6 :   CHECK(!f->Value());
    1934             :   v8::Local<v8::Primitive> u = v8::Undefined(isolate);
    1935           6 :   CHECK(!u->BooleanValue(isolate));
    1936             :   v8::Local<v8::Primitive> n = v8::Null(isolate);
    1937           6 :   CHECK(!n->BooleanValue(isolate));
    1938           6 :   v8::Local<String> str1 = v8_str("");
    1939           6 :   CHECK(!str1->BooleanValue(isolate));
    1940           6 :   v8::Local<String> str2 = v8_str("x");
    1941           6 :   CHECK(str2->BooleanValue(isolate));
    1942          12 :   CHECK(!v8::Number::New(isolate, 0)->BooleanValue(isolate));
    1943          12 :   CHECK(v8::Number::New(isolate, -1)->BooleanValue(isolate));
    1944          12 :   CHECK(v8::Number::New(isolate, 1)->BooleanValue(isolate));
    1945          12 :   CHECK(v8::Number::New(isolate, 42)->BooleanValue(isolate));
    1946          18 :   CHECK(!v8_compile("NaN")
    1947             :              ->Run(env.local())
    1948             :              .ToLocalChecked()
    1949           6 :              ->BooleanValue(isolate));
    1950           6 : }
    1951             : 
    1952             : 
    1953          12 : static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1954           6 :   ApiTestFuzzer::Fuzz();
    1955           6 :   args.GetReturnValue().Set(v8_num(13.4));
    1956           6 : }
    1957             : 
    1958             : 
    1959           6 : static void GetM(Local<String> name,
    1960             :                  const v8::PropertyCallbackInfo<v8::Value>& info) {
    1961           6 :   ApiTestFuzzer::Fuzz();
    1962           6 :   info.GetReturnValue().Set(v8_num(876));
    1963           6 : }
    1964             : 
    1965             : 
    1966       25881 : THREADED_TEST(GlobalPrototype) {
    1967           6 :   v8::Isolate* isolate = CcTest::isolate();
    1968           6 :   v8::HandleScope scope(isolate);
    1969             :   v8::Local<v8::FunctionTemplate> func_templ =
    1970           6 :       v8::FunctionTemplate::New(isolate);
    1971          12 :   func_templ->PrototypeTemplate()->Set(
    1972          12 :       isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
    1973           6 :   v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
    1974           6 :   templ->Set(isolate, "x", v8_num(200));
    1975           6 :   templ->SetAccessor(v8_str("m"), GetM);
    1976          12 :   LocalContext env(nullptr, templ);
    1977             :   v8::Local<Script> script(v8_compile("dummy()"));
    1978           6 :   v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
    1979          12 :   CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
    1980           6 :   CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
    1981          12 :   CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
    1982           6 : }
    1983             : 
    1984             : 
    1985       25881 : THREADED_TEST(ObjectTemplate) {
    1986           6 :   LocalContext env;
    1987           6 :   v8::Isolate* isolate = CcTest::isolate();
    1988          12 :   v8::HandleScope scope(isolate);
    1989             :   Local<v8::FunctionTemplate> acc =
    1990           6 :       v8::FunctionTemplate::New(isolate, Returns42);
    1991          42 :   CHECK(env->Global()
    1992             :             ->Set(env.local(), v8_str("acc"),
    1993             :                   acc->GetFunction(env.local()).ToLocalChecked())
    1994             :             .FromJust());
    1995             : 
    1996           6 :   Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
    1997           6 :   v8::Local<v8::String> class_name = v8_str("the_class_name");
    1998           6 :   fun->SetClassName(class_name);
    1999           6 :   Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
    2000           6 :   templ1->Set(isolate, "x", v8_num(10));
    2001           6 :   templ1->Set(isolate, "y", v8_num(13));
    2002          12 :   templ1->Set(v8_str("foo"), acc);
    2003             :   Local<v8::Object> instance1 =
    2004           6 :       templ1->NewInstance(env.local()).ToLocalChecked();
    2005          12 :   CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
    2006          30 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
    2007           6 :   CHECK(CompileRun("(p.x == 10)")->BooleanValue(isolate));
    2008           6 :   CHECK(CompileRun("(p.y == 13)")->BooleanValue(isolate));
    2009           6 :   CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(isolate));
    2010           6 :   CHECK(CompileRun("(p.foo == acc)")->BooleanValue(isolate));
    2011             :   // Ensure that foo become a data field.
    2012             :   CompileRun("p.foo = function() {}");
    2013           6 :   Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
    2014          12 :   fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
    2015           6 :   Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
    2016           6 :   templ2->Set(isolate, "a", v8_num(12));
    2017             :   templ2->Set(isolate, "b", templ1);
    2018          12 :   templ2->Set(v8_str("bar"), acc);
    2019          12 :   templ2->SetAccessorProperty(v8_str("acc"), acc);
    2020             :   Local<v8::Object> instance2 =
    2021           6 :       templ2->NewInstance(env.local()).ToLocalChecked();
    2022          30 :   CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
    2023           6 :   CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(isolate));
    2024           6 :   CHECK(CompileRun("(q.a == 12)")->BooleanValue(isolate));
    2025           6 :   CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(isolate));
    2026           6 :   CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(isolate));
    2027           6 :   CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(isolate));
    2028           6 :   CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(isolate));
    2029           6 :   CHECK(CompileRun("(q.b !== p)")->BooleanValue(isolate));
    2030           6 :   CHECK(CompileRun("(q.acc == 42)")->BooleanValue(isolate));
    2031           6 :   CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(isolate));
    2032           6 :   CHECK(CompileRun("(q.bar == acc)")->BooleanValue(isolate));
    2033             : 
    2034           6 :   instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
    2035          30 :   CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
    2036           6 :   CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(isolate));
    2037           6 :   CHECK(CompileRun("(q2.a == 12)")->BooleanValue(isolate));
    2038           6 :   CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(isolate));
    2039           6 :   CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(isolate));
    2040           6 :   CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(isolate));
    2041           6 :   CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(isolate));
    2042           6 :   CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(isolate));
    2043           6 :   CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(isolate));
    2044           6 :   CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(isolate));
    2045             : 
    2046           6 :   CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(isolate));
    2047           6 :   CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")->BooleanValue(isolate));
    2048           6 :   CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
    2049             :                    "(desc1.get === acc)")
    2050             :             ->BooleanValue(isolate));
    2051           6 :   CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
    2052             :                    "(desc2.get === acc)")
    2053           6 :             ->BooleanValue(isolate));
    2054           6 : }
    2055             : 
    2056       25881 : THREADED_TEST(IntegerValue) {
    2057           6 :   LocalContext env;
    2058           6 :   v8::Isolate* isolate = CcTest::isolate();
    2059          12 :   v8::HandleScope scope(isolate);
    2060             : 
    2061          24 :   CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
    2062           6 : }
    2063             : 
    2064         126 : static void GetNirk(Local<String> name,
    2065             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2066         126 :   ApiTestFuzzer::Fuzz();
    2067         126 :   info.GetReturnValue().Set(v8_num(900));
    2068         126 : }
    2069             : 
    2070         126 : static void GetRino(Local<String> name,
    2071             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2072         126 :   ApiTestFuzzer::Fuzz();
    2073         126 :   info.GetReturnValue().Set(v8_num(560));
    2074         126 : }
    2075             : 
    2076             : enum ObjectInstantiationMode {
    2077             :   // Create object using ObjectTemplate::NewInstance.
    2078             :   ObjectTemplate_NewInstance,
    2079             :   // Create object using FunctionTemplate::NewInstance on constructor.
    2080             :   Constructor_GetFunction_NewInstance,
    2081             :   // Create object using new operator on constructor.
    2082             :   Constructor_GetFunction_New
    2083             : };
    2084             : 
    2085             : // Test object instance creation using a function template with an instance
    2086             : // template inherited from another function template with accessors and data
    2087             : // properties in prototype template.
    2088          18 : static void TestObjectTemplateInheritedWithPrototype(
    2089             :     ObjectInstantiationMode mode) {
    2090          18 :   LocalContext env;
    2091          18 :   v8::Isolate* isolate = CcTest::isolate();
    2092          36 :   v8::HandleScope scope(isolate);
    2093             : 
    2094          18 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2095          18 :   fun_A->SetClassName(v8_str("A"));
    2096          18 :   v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
    2097          18 :   prototype_templ->Set(isolate, "a", v8_num(113));
    2098          18 :   prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2099          18 :   prototype_templ->Set(isolate, "b", v8_num(153));
    2100             : 
    2101          18 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2102          18 :   v8::Local<v8::String> class_name = v8_str("B");
    2103          18 :   fun_B->SetClassName(class_name);
    2104          18 :   fun_B->Inherit(fun_A);
    2105          18 :   prototype_templ = fun_B->PrototypeTemplate();
    2106          18 :   prototype_templ->Set(isolate, "c", v8_num(713));
    2107          18 :   prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
    2108          18 :   prototype_templ->Set(isolate, "d", v8_num(753));
    2109             : 
    2110          18 :   Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
    2111          18 :   templ->Set(isolate, "x", v8_num(10));
    2112          18 :   templ->Set(isolate, "y", v8_num(13));
    2113             : 
    2114             :   // Perform several iterations to trigger creation from cached boilerplate.
    2115          72 :   for (int i = 0; i < 3; i++) {
    2116             :     Local<v8::Object> instance;
    2117          54 :     switch (mode) {
    2118             :       case ObjectTemplate_NewInstance:
    2119          18 :         instance = templ->NewInstance(env.local()).ToLocalChecked();
    2120          18 :         break;
    2121             : 
    2122             :       case Constructor_GetFunction_NewInstance: {
    2123             :         Local<v8::Function> function_B =
    2124          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2125          18 :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2126             :         break;
    2127             :       }
    2128             :       case Constructor_GetFunction_New: {
    2129             :         Local<v8::Function> function_B =
    2130          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2131          18 :         if (i == 0) {
    2132          24 :           CHECK(env->Global()
    2133             :                     ->Set(env.local(), class_name, function_B)
    2134             :                     .FromJust());
    2135             :         }
    2136             :         instance =
    2137          36 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2138             :         break;
    2139             :       }
    2140             :       default:
    2141           0 :         UNREACHABLE();
    2142             :     }
    2143             : 
    2144         108 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2145         270 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2146             : 
    2147         162 :     CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
    2148         162 :     CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
    2149             : 
    2150         162 :     CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
    2151         162 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2152         162 :     CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
    2153         162 :     CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
    2154         162 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2155         162 :     CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
    2156          18 :   }
    2157          18 : }
    2158             : 
    2159       25881 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
    2160           6 :   TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
    2161           6 : }
    2162             : 
    2163       25881 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
    2164           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
    2165           6 : }
    2166             : 
    2167       25881 : THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
    2168           6 :   TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
    2169           6 : }
    2170             : 
    2171             : // Test object instance creation using a function template without an instance
    2172             : // template inherited from another function template.
    2173          12 : static void TestObjectTemplateInheritedWithoutInstanceTemplate(
    2174             :     ObjectInstantiationMode mode) {
    2175          12 :   LocalContext env;
    2176          12 :   v8::Isolate* isolate = CcTest::isolate();
    2177          24 :   v8::HandleScope scope(isolate);
    2178             : 
    2179          12 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2180          12 :   fun_A->SetClassName(v8_str("A"));
    2181             : 
    2182          12 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2183          12 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2184          12 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2185             : 
    2186          12 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2187          12 :   v8::Local<v8::String> class_name = v8_str("B");
    2188          12 :   fun_B->SetClassName(class_name);
    2189          12 :   fun_B->Inherit(fun_A);
    2190             : 
    2191             :   // Perform several iterations to trigger creation from cached boilerplate.
    2192          48 :   for (int i = 0; i < 3; i++) {
    2193             :     Local<v8::Object> instance;
    2194          36 :     switch (mode) {
    2195             :       case Constructor_GetFunction_NewInstance: {
    2196             :         Local<v8::Function> function_B =
    2197          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2198          18 :         instance = function_B->NewInstance(env.local()).ToLocalChecked();
    2199             :         break;
    2200             :       }
    2201             :       case Constructor_GetFunction_New: {
    2202             :         Local<v8::Function> function_B =
    2203          18 :             fun_B->GetFunction(env.local()).ToLocalChecked();
    2204          18 :         if (i == 0) {
    2205          24 :           CHECK(env->Global()
    2206             :                     ->Set(env.local(), class_name, function_B)
    2207             :                     .FromJust());
    2208             :         }
    2209             :         instance =
    2210          36 :             CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
    2211             :         break;
    2212             :       }
    2213             :       default:
    2214           0 :         UNREACHABLE();
    2215             :     }
    2216             : 
    2217          72 :     CHECK(class_name->StrictEquals(instance->GetConstructorName()));
    2218         180 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2219             : 
    2220         108 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2221         108 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2222          12 :   }
    2223          12 : }
    2224             : 
    2225       25881 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
    2226             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2227           6 :       Constructor_GetFunction_NewInstance);
    2228           6 : }
    2229             : 
    2230       25881 : THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
    2231             :   TestObjectTemplateInheritedWithoutInstanceTemplate(
    2232           6 :       Constructor_GetFunction_New);
    2233           6 : }
    2234             : 
    2235       25881 : THREADED_TEST(TestObjectTemplateClassInheritance) {
    2236           6 :   LocalContext env;
    2237           6 :   v8::Isolate* isolate = CcTest::isolate();
    2238          12 :   v8::HandleScope scope(isolate);
    2239             : 
    2240           6 :   Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2241           6 :   fun_A->SetClassName(v8_str("A"));
    2242             : 
    2243           6 :   Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
    2244           6 :   templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
    2245           6 :   templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
    2246             : 
    2247           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2248           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2249           6 :   fun_B->SetClassName(class_name);
    2250           6 :   fun_B->Inherit(fun_A);
    2251             : 
    2252           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2253             :   v8::Local<v8::Object> b_proto;
    2254             :   v8::Local<v8::Object> c_proto;
    2255             :   // Perform several iterations to make sure the cache doesn't break
    2256             :   // subclassing.
    2257          24 :   for (int i = 0; i < 3; i++) {
    2258             :     Local<v8::Function> function_B =
    2259          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2260          18 :     if (i == 0) {
    2261          24 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2262             :       CompileRun("class C extends B {}");
    2263             :       b_proto =
    2264          12 :           CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
    2265             :       c_proto =
    2266          12 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2267          12 :       CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
    2268             :     }
    2269             :     Local<v8::Object> instance =
    2270          36 :         CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
    2271          36 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2272             : 
    2273          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2274          90 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2275             : 
    2276          54 :     CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2277          54 :     CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2278           6 :   }
    2279           6 : }
    2280             : 
    2281         276 : static void NamedPropertyGetterWhichReturns42(
    2282             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2283         276 :   info.GetReturnValue().Set(v8_num(42));
    2284         276 : }
    2285             : 
    2286       25881 : THREADED_TEST(TestObjectTemplateReflectConstruct) {
    2287           6 :   LocalContext env;
    2288           6 :   v8::Isolate* isolate = CcTest::isolate();
    2289          12 :   v8::HandleScope scope(isolate);
    2290             : 
    2291           6 :   Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2292             :   fun_B->InstanceTemplate()->SetHandler(
    2293          12 :       v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
    2294           6 :   v8::Local<v8::String> class_name = v8_str("B");
    2295           6 :   fun_B->SetClassName(class_name);
    2296             : 
    2297           6 :   v8::Local<v8::String> subclass_name = v8_str("C");
    2298             :   v8::Local<v8::Object> b_proto;
    2299             :   v8::Local<v8::Object> c_proto;
    2300             :   // Perform several iterations to make sure the cache doesn't break
    2301             :   // subclassing.
    2302          24 :   for (int i = 0; i < 3; i++) {
    2303             :     Local<v8::Function> function_B =
    2304          18 :         fun_B->GetFunction(env.local()).ToLocalChecked();
    2305          18 :     if (i == 0) {
    2306          24 :       CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
    2307             :       CompileRun("function C() {}");
    2308             :       c_proto =
    2309          12 :           CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
    2310             :     }
    2311             :     Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
    2312          18 :                                      ->ToObject(env.local())
    2313          18 :                                      .ToLocalChecked();
    2314          36 :     CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
    2315             : 
    2316          36 :     CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
    2317          90 :     CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
    2318             : 
    2319          54 :     CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
    2320          54 :     CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
    2321           6 :   }
    2322           6 : }
    2323             : 
    2324          24 : static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
    2325          12 :   ApiTestFuzzer::Fuzz();
    2326          12 :   args.GetReturnValue().Set(v8_num(17.2));
    2327          12 : }
    2328             : 
    2329             : 
    2330          30 : static void GetKnurd(Local<String> property,
    2331             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    2332          30 :   ApiTestFuzzer::Fuzz();
    2333          30 :   info.GetReturnValue().Set(v8_num(15.2));
    2334          30 : }
    2335             : 
    2336             : 
    2337       25881 : THREADED_TEST(DescriptorInheritance) {
    2338           6 :   v8::Isolate* isolate = CcTest::isolate();
    2339           6 :   v8::HandleScope scope(isolate);
    2340           6 :   v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
    2341          12 :   super->PrototypeTemplate()->Set(isolate, "flabby",
    2342             :                                   v8::FunctionTemplate::New(isolate,
    2343          12 :                                                             GetFlabby));
    2344          12 :   super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
    2345             : 
    2346          12 :   super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
    2347             : 
    2348           6 :   v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
    2349           6 :   base1->Inherit(super);
    2350          12 :   base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
    2351             : 
    2352           6 :   v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
    2353           6 :   base2->Inherit(super);
    2354          12 :   base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
    2355             : 
    2356          12 :   LocalContext env;
    2357             : 
    2358          36 :   CHECK(env->Global()
    2359             :             ->Set(env.local(), v8_str("s"),
    2360             :                   super->GetFunction(env.local()).ToLocalChecked())
    2361             :             .FromJust());
    2362          36 :   CHECK(env->Global()
    2363             :             ->Set(env.local(), v8_str("base1"),
    2364             :                   base1->GetFunction(env.local()).ToLocalChecked())
    2365             :             .FromJust());
    2366          36 :   CHECK(env->Global()
    2367             :             ->Set(env.local(), v8_str("base2"),
    2368             :                   base2->GetFunction(env.local()).ToLocalChecked())
    2369             :             .FromJust());
    2370             : 
    2371             :   // Checks right __proto__ chain.
    2372           6 :   CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
    2373             :             ->BooleanValue(isolate));
    2374           6 :   CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
    2375             :             ->BooleanValue(isolate));
    2376             : 
    2377          18 :   CHECK(v8_compile("s.prototype.PI == 3.14")
    2378             :             ->Run(env.local())
    2379             :             .ToLocalChecked()
    2380             :             ->BooleanValue(isolate));
    2381             : 
    2382             :   // Instance accessor should not be visible on function object or its prototype
    2383           6 :   CHECK(CompileRun("s.knurd == undefined")->BooleanValue(isolate));
    2384           6 :   CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue(isolate));
    2385           6 :   CHECK(
    2386             :       CompileRun("base1.prototype.knurd == undefined")->BooleanValue(isolate));
    2387             : 
    2388          36 :   CHECK(env->Global()
    2389             :             ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
    2390             :                                                   .ToLocalChecked()
    2391             :                                                   ->NewInstance(env.local())
    2392             :                                                   .ToLocalChecked())
    2393             :             .FromJust());
    2394          18 :   CHECK_EQ(17.2,
    2395             :            CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
    2396           6 :   CHECK(CompileRun("'flabby' in obj")->BooleanValue(isolate));
    2397          18 :   CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
    2398           6 :   CHECK(CompileRun("'knurd' in obj")->BooleanValue(isolate));
    2399          18 :   CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
    2400             : 
    2401          36 :   CHECK(env->Global()
    2402             :             ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
    2403             :                                                    .ToLocalChecked()
    2404             :                                                    ->NewInstance(env.local())
    2405             :                                                    .ToLocalChecked())
    2406             :             .FromJust());
    2407          18 :   CHECK_EQ(17.2,
    2408             :            CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
    2409           6 :   CHECK(CompileRun("'flabby' in obj2")->BooleanValue(isolate));
    2410          18 :   CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
    2411           6 :   CHECK(CompileRun("'knurd' in obj2")->BooleanValue(isolate));
    2412          18 :   CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
    2413             : 
    2414             :   // base1 and base2 cannot cross reference to each's prototype
    2415           6 :   CHECK(CompileRun("obj.v2")->IsUndefined());
    2416          12 :   CHECK(CompileRun("obj2.v1")->IsUndefined());
    2417           6 : }
    2418             : 
    2419       25881 : THREADED_TEST(DescriptorInheritance2) {
    2420           6 :   LocalContext env;
    2421           6 :   v8::Isolate* isolate = CcTest::isolate();
    2422          12 :   v8::HandleScope scope(isolate);
    2423           6 :   v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
    2424           6 :   fun_A->SetClassName(v8_str("A"));
    2425          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
    2426          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
    2427          12 :   fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
    2428             : 
    2429           6 :   v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
    2430           6 :   fun_B->SetClassName(v8_str("B"));
    2431           6 :   fun_B->Inherit(fun_A);
    2432             : 
    2433           6 :   v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
    2434           6 :   fun_C->SetClassName(v8_str("C"));
    2435           6 :   fun_C->Inherit(fun_B);
    2436          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
    2437          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
    2438          12 :   fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
    2439             : 
    2440           6 :   v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
    2441           6 :   fun_D->SetClassName(v8_str("D"));
    2442           6 :   fun_D->Inherit(fun_C);
    2443             : 
    2444           6 :   v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
    2445           6 :   fun_E->SetClassName(v8_str("E"));
    2446           6 :   fun_E->Inherit(fun_D);
    2447          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
    2448          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
    2449          12 :   fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
    2450             : 
    2451           6 :   v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
    2452           6 :   fun_F->SetClassName(v8_str("F"));
    2453           6 :   fun_F->Inherit(fun_E);
    2454           6 :   v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
    2455             :   const int kDataPropertiesNumber = 100;
    2456         606 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2457         600 :     v8::Local<v8::Value> val = v8_num(i);
    2458        1200 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2459         600 :     v8::Local<v8::String> name = String::Concat(isolate, v8_str("p"), val_str);
    2460             : 
    2461         600 :     templ->Set(name, val);
    2462         600 :     templ->Set(val_str, val);
    2463             :   }
    2464             : 
    2465          36 :   CHECK(env->Global()
    2466             :             ->Set(env.local(), v8_str("F"),
    2467             :                   fun_F->GetFunction(env.local()).ToLocalChecked())
    2468             :             .FromJust());
    2469             : 
    2470             :   v8::Local<v8::Script> script = v8_compile("o = new F()");
    2471             : 
    2472         606 :   for (int i = 0; i < 100; i++) {
    2473         600 :     v8::HandleScope scope(isolate);
    2474         600 :     script->Run(env.local()).ToLocalChecked();
    2475         600 :   }
    2476           6 :   v8::Local<v8::Object> object = script->Run(env.local())
    2477           6 :                                      .ToLocalChecked()
    2478           6 :                                      ->ToObject(env.local())
    2479           6 :                                      .ToLocalChecked();
    2480             : 
    2481          18 :   CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
    2482          18 :   CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
    2483          18 :   CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
    2484             : 
    2485          18 :   CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
    2486          18 :   CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
    2487          18 :   CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
    2488             : 
    2489          18 :   CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
    2490          18 :   CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
    2491          18 :   CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
    2492             : 
    2493         600 :   for (int i = 0; i < kDataPropertiesNumber; i++) {
    2494         600 :     v8::Local<v8::Value> val = v8_num(i);
    2495        1800 :     v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
    2496         600 :     v8::Local<v8::String> name = String::Concat(isolate, v8_str("p"), val_str);
    2497             : 
    2498        2400 :     CHECK_EQ(i, object->Get(env.local(), name)
    2499             :                     .ToLocalChecked()
    2500             :                     ->IntegerValue(env.local())
    2501             :                     .FromJust());
    2502        1800 :     CHECK_EQ(i, object->Get(env.local(), val)
    2503             :                     .ToLocalChecked()
    2504             :                     ->IntegerValue(env.local())
    2505             :                     .FromJust());
    2506           6 :   }
    2507           6 : }
    2508             : 
    2509             : 
    2510             : // Helper functions for Interceptor/Accessor interaction tests
    2511             : 
    2512          36 : void SimpleAccessorGetter(Local<String> name,
    2513             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2514             :   Local<Object> self = Local<Object>::Cast(info.This());
    2515             :   info.GetReturnValue().Set(
    2516             :       self->Get(info.GetIsolate()->GetCurrentContext(),
    2517         144 :                 String::Concat(info.GetIsolate(), v8_str("accessor_"), name))
    2518          36 :           .ToLocalChecked());
    2519          36 : }
    2520             : 
    2521           6 : void SimpleAccessorSetter(Local<String> name, Local<Value> value,
    2522             :                           const v8::PropertyCallbackInfo<void>& info) {
    2523             :   Local<Object> self = Local<Object>::Cast(info.This());
    2524          24 :   CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
    2525             :                   String::Concat(info.GetIsolate(), v8_str("accessor_"), name),
    2526             :                   value)
    2527             :             .FromJust());
    2528           6 : }
    2529             : 
    2530          36 : void SymbolAccessorGetter(Local<Name> name,
    2531             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
    2532          36 :   CHECK(name->IsSymbol());
    2533             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2534          72 :   if (sym->Name()->IsUndefined())
    2535          36 :     return;
    2536          36 :   SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
    2537             : }
    2538             : 
    2539           6 : void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
    2540             :                           const v8::PropertyCallbackInfo<void>& info) {
    2541           6 :   CHECK(name->IsSymbol());
    2542             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2543          12 :   if (sym->Name()->IsUndefined())
    2544           6 :     return;
    2545           6 :   SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
    2546             : }
    2547             : 
    2548           5 : void SymbolAccessorGetterReturnsDefault(
    2549             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2550           5 :   CHECK(name->IsSymbol());
    2551             :   Local<Symbol> sym = Local<Symbol>::Cast(name);
    2552          15 :   if (sym->Name()->IsUndefined()) return;
    2553             :   info.GetReturnValue().Set(info.Data());
    2554             : }
    2555             : 
    2556           5 : static void ThrowingSymbolAccessorGetter(
    2557             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2558          10 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
    2559           5 : }
    2560             : 
    2561             : 
    2562       25881 : THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
    2563           6 :   v8::Isolate* isolate = CcTest::isolate();
    2564           6 :   v8::HandleScope scope(isolate);
    2565          12 :   LocalContext env;
    2566             :   v8::Local<v8::Value> res = CompileRun("var a = []; a;");
    2567             :   i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
    2568          12 :   CHECK_EQ(1, a->map()->instance_descriptors()->number_of_descriptors());
    2569             :   CompileRun("Object.defineProperty(a, 'length', { writable: false });");
    2570          12 :   CHECK_EQ(0, a->map()->instance_descriptors()->number_of_descriptors());
    2571             :   // But we should still have an AccessorInfo.
    2572          12 :   i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
    2573             :   i::LookupIterator it(CcTest::i_isolate(), a, name,
    2574           6 :                        i::LookupIterator::OWN_SKIP_INTERCEPTOR);
    2575           6 :   CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
    2576          24 :   CHECK(it.GetAccessors()->IsAccessorInfo());
    2577           6 : }
    2578             : 
    2579             : 
    2580       25881 : THREADED_TEST(UndefinedIsNotEnumerable) {
    2581           6 :   LocalContext env;
    2582          12 :   v8::HandleScope scope(env->GetIsolate());
    2583             :   v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
    2584          12 :   CHECK(result->IsFalse());
    2585           6 : }
    2586             : 
    2587             : 
    2588             : v8::Local<Script> call_recursively_script;
    2589             : static const int kTargetRecursionDepth = 100;  // near maximum
    2590             : 
    2591         606 : static void CallScriptRecursivelyCall(
    2592        3012 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2593         606 :   ApiTestFuzzer::Fuzz();
    2594         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2595             :   int depth = args.This()
    2596        1212 :                   ->Get(context, v8_str("depth"))
    2597         606 :                   .ToLocalChecked()
    2598             :                   ->Int32Value(context)
    2599        1212 :                   .FromJust();
    2600         612 :   if (depth == kTargetRecursionDepth) return;
    2601        3000 :   CHECK(args.This()
    2602             :             ->Set(context, v8_str("depth"),
    2603             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2604             :             .FromJust());
    2605             :   args.GetReturnValue().Set(
    2606         600 :       call_recursively_script->Run(context).ToLocalChecked());
    2607             : }
    2608             : 
    2609             : 
    2610         606 : static void CallFunctionRecursivelyCall(
    2611        4212 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2612         606 :   ApiTestFuzzer::Fuzz();
    2613         606 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    2614             :   int depth = args.This()
    2615        1212 :                   ->Get(context, v8_str("depth"))
    2616         606 :                   .ToLocalChecked()
    2617             :                   ->Int32Value(context)
    2618        1212 :                   .FromJust();
    2619         606 :   if (depth == kTargetRecursionDepth) {
    2620             :     printf("[depth = %d]\n", depth);
    2621         612 :     return;
    2622             :   }
    2623        3000 :   CHECK(args.This()
    2624             :             ->Set(context, v8_str("depth"),
    2625             :                   v8::Integer::New(args.GetIsolate(), depth + 1))
    2626             :             .FromJust());
    2627             :   v8::Local<Value> function =
    2628             :       args.This()
    2629        1200 :           ->Get(context, v8_str("callFunctionRecursively"))
    2630         600 :           .ToLocalChecked();
    2631             :   args.GetReturnValue().Set(function.As<Function>()
    2632         600 :                                 ->Call(context, args.This(), 0, nullptr)
    2633         600 :                                 .ToLocalChecked());
    2634             : }
    2635             : 
    2636             : 
    2637       25881 : THREADED_TEST(DeepCrossLanguageRecursion) {
    2638           6 :   v8::Isolate* isolate = CcTest::isolate();
    2639           6 :   v8::HandleScope scope(isolate);
    2640           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    2641             :   global->Set(v8_str("callScriptRecursively"),
    2642          18 :               v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
    2643             :   global->Set(v8_str("callFunctionRecursively"),
    2644          18 :               v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
    2645          12 :   LocalContext env(nullptr, global);
    2646             : 
    2647          36 :   CHECK(env->Global()
    2648             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2649             :             .FromJust());
    2650           6 :   call_recursively_script = v8_compile("callScriptRecursively()");
    2651          12 :   call_recursively_script->Run(env.local()).ToLocalChecked();
    2652           6 :   call_recursively_script = v8::Local<Script>();
    2653             : 
    2654          36 :   CHECK(env->Global()
    2655             :             ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
    2656             :             .FromJust());
    2657           6 :   CompileRun("callFunctionRecursively()");
    2658           6 : }
    2659             : 
    2660             : 
    2661          24 : static void ThrowingPropertyHandlerGet(
    2662             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2663             :   // Since this interceptor is used on "with" objects, the runtime will look up
    2664             :   // @@unscopables.  Punt.
    2665          48 :   if (key->IsSymbol()) return;
    2666          12 :   ApiTestFuzzer::Fuzz();
    2667          24 :   info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
    2668             : }
    2669             : 
    2670             : 
    2671           0 : static void ThrowingPropertyHandlerSet(
    2672             :     Local<Name> key, Local<Value>,
    2673             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2674           0 :   info.GetIsolate()->ThrowException(key);
    2675             :   info.GetReturnValue().SetUndefined();  // not the same as empty handle
    2676           0 : }
    2677             : 
    2678             : 
    2679       25881 : THREADED_TEST(CallbackExceptionRegression) {
    2680           6 :   v8::Isolate* isolate = CcTest::isolate();
    2681           6 :   v8::HandleScope scope(isolate);
    2682           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    2683             :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2684           6 :       ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
    2685          12 :   LocalContext env;
    2686          36 :   CHECK(env->Global()
    2687             :             ->Set(env.local(), v8_str("obj"),
    2688             :                   obj->NewInstance(env.local()).ToLocalChecked())
    2689             :             .FromJust());
    2690             :   v8::Local<Value> otto =
    2691           6 :       CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
    2692          18 :   CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
    2693             :   v8::Local<Value> netto =
    2694           6 :       CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
    2695          24 :   CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
    2696           6 : }
    2697             : 
    2698             : 
    2699       25881 : THREADED_TEST(FunctionPrototype) {
    2700           6 :   v8::Isolate* isolate = CcTest::isolate();
    2701           6 :   v8::HandleScope scope(isolate);
    2702           6 :   Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
    2703          24 :   Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
    2704          12 :   LocalContext env;
    2705          36 :   CHECK(env->Global()
    2706             :             ->Set(env.local(), v8_str("Foo"),
    2707             :                   Foo->GetFunction(env.local()).ToLocalChecked())
    2708             :             .FromJust());
    2709           6 :   Local<Script> script = v8_compile("Foo.prototype.plak");
    2710          12 :   CHECK_EQ(v8_run_int32value(script), 321);
    2711           6 : }
    2712             : 
    2713       25881 : THREADED_TEST(InternalFields) {
    2714           6 :   LocalContext env;
    2715           6 :   v8::Isolate* isolate = env->GetIsolate();
    2716          12 :   v8::HandleScope scope(isolate);
    2717             : 
    2718           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2719           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2720           6 :   instance_templ->SetInternalFieldCount(1);
    2721           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2722           6 :                               .ToLocalChecked()
    2723           6 :                               ->NewInstance(env.local())
    2724             :                               .ToLocalChecked();
    2725           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2726           6 :   CHECK(obj->GetInternalField(0)->IsUndefined());
    2727           6 :   obj->SetInternalField(0, v8_num(17));
    2728          24 :   CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2729           6 : }
    2730             : 
    2731       25880 : TEST(InternalFieldsSubclassing) {
    2732           5 :   LocalContext env;
    2733           5 :   v8::Isolate* isolate = env->GetIsolate();
    2734             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    2735          10 :   v8::HandleScope scope(isolate);
    2736          65 :   for (int nof_embedder_fields = 0;
    2737             :        nof_embedder_fields < i::JSObject::kMaxEmbedderFields;
    2738             :        nof_embedder_fields++) {
    2739          60 :     Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2740          60 :     Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2741          60 :     instance_templ->SetInternalFieldCount(nof_embedder_fields);
    2742             :     Local<Function> constructor =
    2743          60 :         templ->GetFunction(env.local()).ToLocalChecked();
    2744             :     // Check that instances have the correct NOF properties.
    2745             :     Local<v8::Object> obj =
    2746          60 :         constructor->NewInstance(env.local()).ToLocalChecked();
    2747             : 
    2748             :     i::Handle<i::JSObject> i_obj =
    2749          60 :         i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj));
    2750          60 :     CHECK_EQ(nof_embedder_fields, obj->InternalFieldCount());
    2751          60 :     CHECK_EQ(0, i_obj->map()->GetInObjectProperties());
    2752             :     // Check writing and reading internal fields.
    2753         330 :     for (int j = 0; j < nof_embedder_fields; j++) {
    2754         330 :       CHECK(obj->GetInternalField(j)->IsUndefined());
    2755         330 :       int value = 17 + j;
    2756         330 :       obj->SetInternalField(j, v8_num(value));
    2757             :     }
    2758         330 :     for (int j = 0; j < nof_embedder_fields; j++) {
    2759         330 :       int value = 17 + j;
    2760         990 :       CHECK_EQ(value,
    2761             :                obj->GetInternalField(j)->Int32Value(env.local()).FromJust());
    2762             :     }
    2763         300 :     CHECK(env->Global()
    2764             :               ->Set(env.local(), v8_str("BaseClass"), constructor)
    2765             :               .FromJust());
    2766             :     // Create various levels of subclasses to stress instance size calculation.
    2767             :     const int kMaxNofProperties =
    2768             :         i::JSObject::kMaxInObjectProperties -
    2769          60 :         nof_embedder_fields * i::kEmbedderDataSlotSizeInTaggedSlots;
    2770             :     // Select only a few values to speed up the test.
    2771             :     int sizes[] = {0,
    2772             :                    1,
    2773             :                    2,
    2774             :                    3,
    2775             :                    4,
    2776             :                    5,
    2777             :                    6,
    2778          60 :                    kMaxNofProperties / 4,
    2779          60 :                    kMaxNofProperties / 2,
    2780          60 :                    kMaxNofProperties - 2,
    2781          60 :                    kMaxNofProperties - 1,
    2782          60 :                    kMaxNofProperties + 1,
    2783          60 :                    kMaxNofProperties + 2,
    2784          60 :                    kMaxNofProperties * 2,
    2785         480 :                    kMaxNofProperties * 2};
    2786         960 :     for (size_t i = 0; i < arraysize(sizes); i++) {
    2787         900 :       int nof_properties = sizes[i];
    2788         900 :       bool in_object_only = nof_properties <= kMaxNofProperties;
    2789         900 :       std::ostringstream src;
    2790             :       // Assembler source string for a subclass with {nof_properties}
    2791             :       // in-object properties.
    2792         900 :       src << "(function() {\n"
    2793         900 :           << "  class SubClass extends BaseClass {\n"
    2794         900 :           << "    constructor() {\n"
    2795         900 :           << "      super();\n";
    2796             :       // Set {nof_properties} instance properties in the constructor.
    2797      131535 :       for (int j = 0; j < nof_properties; j++) {
    2798      130635 :         src << "      this.property" << j << " = " << j << ";\n";
    2799             :       }
    2800         900 :       src << "    }\n"
    2801         900 :           << "  };\n"
    2802         900 :           << "  let instance;\n"
    2803         900 :           << "  for (let i = 0; i < 3; i++) {\n"
    2804         900 :           << "    instance = new SubClass();\n"
    2805         900 :           << "  }"
    2806         900 :           << "  return instance;\n"
    2807         900 :           << "})();";
    2808         900 :       Local<v8::Object> value = CompileRun(src.str().c_str()).As<v8::Object>();
    2809             : 
    2810             :       i::Handle<i::JSObject> i_value =
    2811         900 :           i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*value));
    2812             : #ifdef VERIFY_HEAP
    2813             :       i_value->HeapObjectVerify(i_isolate);
    2814             :       i_value->map()->HeapObjectVerify(i_isolate);
    2815             :       i_value->map()->FindRootMap(i_isolate)->HeapObjectVerify(i_isolate);
    2816             : #endif
    2817         900 :       CHECK_EQ(nof_embedder_fields, value->InternalFieldCount());
    2818         900 :       if (in_object_only) {
    2819         660 :         CHECK_LE(nof_properties, i_value->map()->GetInObjectProperties());
    2820             :       } else {
    2821         240 :         CHECK_LE(kMaxNofProperties, i_value->map()->GetInObjectProperties());
    2822             :       }
    2823             : 
    2824             :       // Make Sure we get the precise property count.
    2825        1800 :       i_value->map()->FindRootMap(i_isolate)->CompleteInobjectSlackTracking(
    2826         900 :           i_isolate);
    2827             :       // TODO(cbruni): fix accounting to make this condition true.
    2828             :       // CHECK_EQ(0, i_value->map()->UnusedPropertyFields());
    2829         900 :       if (in_object_only) {
    2830         660 :         CHECK_EQ(nof_properties, i_value->map()->GetInObjectProperties());
    2831             :       } else {
    2832         240 :         CHECK_LE(kMaxNofProperties, i_value->map()->GetInObjectProperties());
    2833             :       }
    2834         900 :     }
    2835           5 :   }
    2836           5 : }
    2837             : 
    2838       25881 : THREADED_TEST(InternalFieldsOfRegularObjects) {
    2839           6 :   LocalContext env;
    2840           6 :   v8::Isolate* isolate = env->GetIsolate();
    2841          12 :   v8::HandleScope scope(isolate);
    2842             : 
    2843           6 :   const char* sources[] = {"new Object()", "{ a: 'a property' }", "arguments"};
    2844          24 :   for (size_t i = 0; i < arraysize(sources); ++i) {
    2845             :     i::ScopedVector<char> source(128);
    2846          18 :     i::SNPrintF(source, "(function() { return %s })()", sources[i]);
    2847             :     v8::Local<v8::Object> obj = CompileRun(source.start()).As<v8::Object>();
    2848          18 :     CHECK_EQ(0, obj->InternalFieldCount());
    2849           6 :   }
    2850           6 : }
    2851             : 
    2852       25881 : THREADED_TEST(GlobalObjectInternalFields) {
    2853           6 :   v8::Isolate* isolate = CcTest::isolate();
    2854           6 :   v8::HandleScope scope(isolate);
    2855           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
    2856           6 :   global_template->SetInternalFieldCount(1);
    2857          12 :   LocalContext env(nullptr, global_template);
    2858           6 :   v8::Local<v8::Object> global_proxy = env->Global();
    2859           6 :   v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
    2860           6 :   CHECK_EQ(1, global->InternalFieldCount());
    2861           6 :   CHECK(global->GetInternalField(0)->IsUndefined());
    2862           6 :   global->SetInternalField(0, v8_num(17));
    2863          24 :   CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
    2864           6 : }
    2865             : 
    2866             : 
    2867       25881 : THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
    2868           6 :   LocalContext env;
    2869          12 :   v8::HandleScope scope(CcTest::isolate());
    2870             : 
    2871           6 :   v8::Local<v8::Object> global = env->Global();
    2872          18 :   CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
    2873          18 :   CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
    2874           6 : }
    2875             : 
    2876          24 : static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
    2877             :                                                void* value) {
    2878          24 :   CHECK(HAS_SMI_TAG(reinterpret_cast<i::Address>(value)));
    2879          24 :   obj->SetAlignedPointerInInternalField(0, value);
    2880          24 :   CcTest::CollectAllGarbage();
    2881          24 :   CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
    2882          24 : }
    2883             : 
    2884       25881 : THREADED_TEST(InternalFieldsAlignedPointers) {
    2885           6 :   LocalContext env;
    2886           6 :   v8::Isolate* isolate = env->GetIsolate();
    2887          12 :   v8::HandleScope scope(isolate);
    2888             : 
    2889           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2890           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2891           6 :   instance_templ->SetInternalFieldCount(1);
    2892           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2893           6 :                               .ToLocalChecked()
    2894           6 :                               ->NewInstance(env.local())
    2895             :                               .ToLocalChecked();
    2896           6 :   CHECK_EQ(1, obj->InternalFieldCount());
    2897             : 
    2898           6 :   CheckAlignedPointerInInternalField(obj, nullptr);
    2899             : 
    2900           6 :   int* heap_allocated = new int[100];
    2901           6 :   CheckAlignedPointerInInternalField(obj, heap_allocated);
    2902           6 :   delete[] heap_allocated;
    2903             : 
    2904             :   int stack_allocated[100];
    2905           6 :   CheckAlignedPointerInInternalField(obj, stack_allocated);
    2906             : 
    2907             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2908           6 :   CheckAlignedPointerInInternalField(obj, huge);
    2909             : 
    2910             :   v8::Global<v8::Object> persistent(isolate, obj);
    2911           6 :   CHECK_EQ(1, Object::InternalFieldCount(persistent));
    2912          12 :   CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
    2913           6 : }
    2914             : 
    2915       25881 : THREADED_TEST(SetAlignedPointerInInternalFields) {
    2916           6 :   LocalContext env;
    2917           6 :   v8::Isolate* isolate = env->GetIsolate();
    2918          12 :   v8::HandleScope scope(isolate);
    2919             : 
    2920           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    2921           6 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    2922           6 :   instance_templ->SetInternalFieldCount(2);
    2923           6 :   Local<v8::Object> obj = templ->GetFunction(env.local())
    2924           6 :                               .ToLocalChecked()
    2925           6 :                               ->NewInstance(env.local())
    2926             :                               .ToLocalChecked();
    2927           6 :   CHECK_EQ(2, obj->InternalFieldCount());
    2928             : 
    2929           6 :   int* heap_allocated_1 = new int[100];
    2930           6 :   int* heap_allocated_2 = new int[100];
    2931           6 :   int indices[] = {0, 1};
    2932           6 :   void* values[] = {heap_allocated_1, heap_allocated_2};
    2933             : 
    2934           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2935           6 :   CcTest::CollectAllGarbage();
    2936           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(0));
    2937           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(1));
    2938             : 
    2939           6 :   indices[0] = 1;
    2940           6 :   indices[1] = 0;
    2941           6 :   obj->SetAlignedPointerInInternalFields(2, indices, values);
    2942           6 :   CcTest::CollectAllGarbage();
    2943           6 :   CHECK_EQ(heap_allocated_2, obj->GetAlignedPointerFromInternalField(0));
    2944           6 :   CHECK_EQ(heap_allocated_1, obj->GetAlignedPointerFromInternalField(1));
    2945             : 
    2946           6 :   delete[] heap_allocated_1;
    2947          12 :   delete[] heap_allocated_2;
    2948           6 : }
    2949             : 
    2950          24 : static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
    2951             :                                               void* value) {
    2952          24 :   CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
    2953          24 :   (*env)->SetAlignedPointerInEmbedderData(index, value);
    2954          24 :   CcTest::CollectAllGarbage();
    2955          24 :   CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
    2956          24 : }
    2957             : 
    2958             : 
    2959             : static void* AlignedTestPointer(int i) {
    2960        1200 :   return reinterpret_cast<void*>(i * 1234);
    2961             : }
    2962             : 
    2963             : 
    2964       25881 : THREADED_TEST(EmbedderDataAlignedPointers) {
    2965           6 :   LocalContext env;
    2966          12 :   v8::HandleScope scope(env->GetIsolate());
    2967             : 
    2968           6 :   CheckAlignedPointerInEmbedderData(&env, 0, nullptr);
    2969           6 :   CHECK_EQ(1, (*env)->GetNumberOfEmbedderDataFields());
    2970             : 
    2971           6 :   int* heap_allocated = new int[100];
    2972           6 :   CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
    2973           6 :   CHECK_EQ(2, (*env)->GetNumberOfEmbedderDataFields());
    2974           6 :   delete[] heap_allocated;
    2975             : 
    2976             :   int stack_allocated[100];
    2977           6 :   CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
    2978           6 :   CHECK_EQ(3, (*env)->GetNumberOfEmbedderDataFields());
    2979             : 
    2980             :   void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
    2981           6 :   CheckAlignedPointerInEmbedderData(&env, 3, huge);
    2982           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    2983             : 
    2984             :   // Test growing of the embedder data's backing store.
    2985         600 :   for (int i = 0; i < 100; i++) {
    2986         600 :     env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
    2987             :   }
    2988           6 :   CcTest::CollectAllGarbage();
    2989         606 :   for (int i = 0; i < 100; i++) {
    2990         600 :     CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
    2991           6 :   }
    2992           6 : }
    2993             : 
    2994          30 : static void CheckEmbedderData(LocalContext* env, int index,
    2995             :                               v8::Local<Value> data) {
    2996          30 :   (*env)->SetEmbedderData(index, data);
    2997          30 :   CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
    2998          30 : }
    2999             : 
    3000             : 
    3001       25881 : THREADED_TEST(EmbedderData) {
    3002           6 :   LocalContext env;
    3003           6 :   v8::Isolate* isolate = env->GetIsolate();
    3004          12 :   v8::HandleScope scope(isolate);
    3005             : 
    3006           6 :   CHECK_EQ(0, (*env)->GetNumberOfEmbedderDataFields());
    3007          12 :   CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
    3008           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3009          12 :   CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
    3010           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3011          12 :   CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
    3012           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3013           6 :   CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
    3014           6 :   CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
    3015           6 :   CheckEmbedderData(&env, 211, v8::Boolean::New(isolate, true));
    3016          12 :   CHECK_EQ(212, (*env)->GetNumberOfEmbedderDataFields());
    3017           6 : }
    3018             : 
    3019             : 
    3020       25881 : THREADED_TEST(IdentityHash) {
    3021           6 :   LocalContext env;
    3022           6 :   v8::Isolate* isolate = env->GetIsolate();
    3023          12 :   v8::HandleScope scope(isolate);
    3024             : 
    3025             :   // Ensure that the test starts with an fresh heap to test whether the hash
    3026             :   // code is based on the address.
    3027           6 :   CcTest::CollectAllGarbage();
    3028           6 :   Local<v8::Object> obj = v8::Object::New(isolate);
    3029           6 :   int hash = obj->GetIdentityHash();
    3030           6 :   int hash1 = obj->GetIdentityHash();
    3031           6 :   CHECK_EQ(hash, hash1);
    3032          12 :   int hash2 = v8::Object::New(isolate)->GetIdentityHash();
    3033             :   // Since the identity hash is essentially a random number two consecutive
    3034             :   // objects should not be assigned the same hash code. If the test below fails
    3035             :   // the random number generator should be evaluated.
    3036           6 :   CHECK_NE(hash, hash2);
    3037           6 :   CcTest::CollectAllGarbage();
    3038          12 :   int hash3 = v8::Object::New(isolate)->GetIdentityHash();
    3039             :   // Make sure that the identity hash is not based on the initial address of
    3040             :   // the object alone. If the test below fails the random number generator
    3041             :   // should be evaluated.
    3042           6 :   CHECK_NE(hash, hash3);
    3043           6 :   int hash4 = obj->GetIdentityHash();
    3044           6 :   CHECK_EQ(hash, hash4);
    3045             : 
    3046             :   // Check identity hashes behaviour in the presence of JS accessors.
    3047             :   // Put a getter for 'v8::IdentityHash' on the Object's prototype:
    3048             :   {
    3049             :     CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
    3050           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    3051           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    3052          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    3053             :   }
    3054             :   {
    3055             :     CompileRun(
    3056             :         "function cnst() { return 42; };\n"
    3057             :         "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
    3058           6 :     Local<v8::Object> o1 = v8::Object::New(isolate);
    3059           6 :     Local<v8::Object> o2 = v8::Object::New(isolate);
    3060          12 :     CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
    3061           6 :   }
    3062           6 : }
    3063             : 
    3064             : 
    3065          12 : void GlobalProxyIdentityHash(bool set_in_js) {
    3066          12 :   LocalContext env;
    3067          12 :   v8::Isolate* isolate = env->GetIsolate();
    3068             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    3069          24 :   v8::HandleScope scope(isolate);
    3070          12 :   Local<Object> global_proxy = env->Global();
    3071             :   i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
    3072          60 :   CHECK(env->Global()
    3073             :             ->Set(env.local(), v8_str("global"), global_proxy)
    3074             :             .FromJust());
    3075             :   int32_t hash1;
    3076          12 :   if (set_in_js) {
    3077             :     CompileRun("var m = new Set(); m.add(global);");
    3078           6 :     i::Object original_hash = i_global_proxy->GetHash();
    3079           6 :     CHECK(original_hash->IsSmi());
    3080           6 :     hash1 = i::Smi::ToInt(original_hash);
    3081             :   } else {
    3082          12 :     hash1 = i_global_proxy->GetOrCreateHash(i_isolate)->value();
    3083             :   }
    3084             :   // Hash should be retained after being detached.
    3085          12 :   env->DetachGlobal();
    3086          12 :   int hash2 = global_proxy->GetIdentityHash();
    3087          12 :   CHECK_EQ(hash1, hash2);
    3088             :   {
    3089             :     // Re-attach global proxy to a new context, hash should stay the same.
    3090          12 :     LocalContext env2(nullptr, Local<ObjectTemplate>(), global_proxy);
    3091          12 :     int hash3 = global_proxy->GetIdentityHash();
    3092          12 :     CHECK_EQ(hash1, hash3);
    3093          12 :   }
    3094          12 : }
    3095             : 
    3096             : 
    3097       25881 : THREADED_TEST(GlobalProxyIdentityHash) {
    3098           6 :   GlobalProxyIdentityHash(true);
    3099           6 :   GlobalProxyIdentityHash(false);
    3100           6 : }
    3101             : 
    3102             : 
    3103       25880 : TEST(SymbolIdentityHash) {
    3104           5 :   LocalContext env;
    3105           5 :   v8::Isolate* isolate = env->GetIsolate();
    3106          10 :   v8::HandleScope scope(isolate);
    3107             : 
    3108             :   {
    3109           5 :     Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
    3110           5 :     int hash = symbol->GetIdentityHash();
    3111           5 :     int hash1 = symbol->GetIdentityHash();
    3112           5 :     CHECK_EQ(hash, hash1);
    3113           5 :     CcTest::CollectAllGarbage();
    3114           5 :     int hash3 = symbol->GetIdentityHash();
    3115           5 :     CHECK_EQ(hash, hash3);
    3116             :   }
    3117             : 
    3118             :   {
    3119             :     v8::Local<v8::Symbol> js_symbol =
    3120             :         CompileRun("Symbol('foo')").As<v8::Symbol>();
    3121           5 :     int hash = js_symbol->GetIdentityHash();
    3122           5 :     int hash1 = js_symbol->GetIdentityHash();
    3123           5 :     CHECK_EQ(hash, hash1);
    3124           5 :     CcTest::CollectAllGarbage();
    3125           5 :     int hash3 = js_symbol->GetIdentityHash();
    3126           5 :     CHECK_EQ(hash, hash3);
    3127           5 :   }
    3128           5 : }
    3129             : 
    3130             : 
    3131       25880 : TEST(StringIdentityHash) {
    3132           5 :   LocalContext env;
    3133           5 :   v8::Isolate* isolate = env->GetIsolate();
    3134          10 :   v8::HandleScope scope(isolate);
    3135             : 
    3136           5 :   Local<v8::String> str = v8_str("str1");
    3137           5 :   int hash = str->GetIdentityHash();
    3138           5 :   int hash1 = str->GetIdentityHash();
    3139           5 :   CHECK_EQ(hash, hash1);
    3140           5 :   CcTest::CollectAllGarbage();
    3141           5 :   int hash3 = str->GetIdentityHash();
    3142           5 :   CHECK_EQ(hash, hash3);
    3143             : 
    3144           5 :   Local<v8::String> str2 = v8_str("str1");
    3145           5 :   int hash4 = str2->GetIdentityHash();
    3146          10 :   CHECK_EQ(hash, hash4);
    3147           5 : }
    3148             : 
    3149             : 
    3150       25881 : THREADED_TEST(SymbolProperties) {
    3151           6 :   LocalContext env;
    3152           6 :   v8::Isolate* isolate = env->GetIsolate();
    3153          12 :   v8::HandleScope scope(isolate);
    3154             : 
    3155           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3156           6 :   v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
    3157           6 :   v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
    3158           6 :   v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
    3159           6 :   v8::Local<v8::Symbol> sym4 = v8::Symbol::New(isolate, v8_str("native"));
    3160             : 
    3161           6 :   CcTest::CollectAllGarbage();
    3162             : 
    3163             :   // Check basic symbol functionality.
    3164           6 :   CHECK(sym1->IsSymbol());
    3165           6 :   CHECK(sym2->IsSymbol());
    3166           6 :   CHECK(!obj->IsSymbol());
    3167             : 
    3168          12 :   CHECK(sym1->Equals(env.local(), sym1).FromJust());
    3169          12 :   CHECK(sym2->Equals(env.local(), sym2).FromJust());
    3170          12 :   CHECK(!sym1->Equals(env.local(), sym2).FromJust());
    3171          12 :   CHECK(!sym2->Equals(env.local(), sym1).FromJust());
    3172           6 :   CHECK(sym1->StrictEquals(sym1));
    3173           6 :   CHECK(sym2->StrictEquals(sym2));
    3174           6 :   CHECK(!sym1->StrictEquals(sym2));
    3175           6 :   CHECK(!sym2->StrictEquals(sym1));
    3176             : 
    3177          24 :   CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
    3178             : 
    3179             :   v8::Local<v8::Value> sym_val = sym2;
    3180           6 :   CHECK(sym_val->IsSymbol());
    3181          12 :   CHECK(sym_val->Equals(env.local(), sym2).FromJust());
    3182           6 :   CHECK(sym_val->StrictEquals(sym2));
    3183          12 :   CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
    3184             : 
    3185           6 :   v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
    3186           6 :   CHECK(sym_obj->IsSymbolObject());
    3187           6 :   CHECK(!sym2->IsSymbolObject());
    3188           6 :   CHECK(!obj->IsSymbolObject());
    3189          12 :   CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
    3190           6 :   CHECK(!sym_obj->StrictEquals(sym2));
    3191          12 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3192             :             ->Equals(env.local(), sym_obj)
    3193             :             .FromJust());
    3194          18 :   CHECK(v8::SymbolObject::Cast(*sym_obj)
    3195             :             ->ValueOf()
    3196             :             ->Equals(env.local(), sym2)
    3197             :             .FromJust());
    3198             : 
    3199             :   // Make sure delete of a non-existent symbol property works.
    3200          12 :   CHECK(obj->Delete(env.local(), sym1).FromJust());
    3201          12 :   CHECK(!obj->Has(env.local(), sym1).FromJust());
    3202             : 
    3203          18 :   CHECK(
    3204             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
    3205          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3206          24 :   CHECK_EQ(1503, obj->Get(env.local(), sym1)
    3207             :                      .ToLocalChecked()
    3208             :                      ->Int32Value(env.local())
    3209             :                      .FromJust());
    3210          18 :   CHECK(
    3211             :       obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
    3212          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3213          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3214             :                      .ToLocalChecked()
    3215             :                      ->Int32Value(env.local())
    3216             :                      .FromJust());
    3217          12 :   CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
    3218             : 
    3219          12 :   CHECK_EQ(0u,
    3220             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3221             :   unsigned num_props =
    3222          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3223          24 :   CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
    3224             :             .FromJust());
    3225          12 :   CHECK_EQ(1u,
    3226             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3227          12 :   CHECK_EQ(num_props + 1,
    3228             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3229             : 
    3230           6 :   CcTest::CollectAllGarbage();
    3231             : 
    3232          12 :   CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
    3233             :                          SymbolAccessorSetter)
    3234             :             .FromJust());
    3235          12 :   CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
    3236          18 :   CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
    3237          30 :   CHECK(obj->Get(env.local(), sym3)
    3238             :             .ToLocalChecked()
    3239             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3240             :             .FromJust());
    3241          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3242             :             .ToLocalChecked()
    3243             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3244             :             .FromJust());
    3245             : 
    3246          12 :   CHECK(obj->SetNativeDataProperty(env.local(), sym4, SymbolAccessorGetter)
    3247             :             .FromJust());
    3248          12 :   CHECK(obj->Get(env.local(), sym4).ToLocalChecked()->IsUndefined());
    3249          24 :   CHECK(obj->Set(env.local(), v8_str("accessor_native"),
    3250             :                  v8::Integer::New(isolate, 123))
    3251             :             .FromJust());
    3252          24 :   CHECK_EQ(123, obj->Get(env.local(), sym4)
    3253             :                     .ToLocalChecked()
    3254             :                     ->Int32Value(env.local())
    3255             :                     .FromJust());
    3256          18 :   CHECK(obj->Set(env.local(), sym4, v8::Integer::New(isolate, 314)).FromJust());
    3257          30 :   CHECK(obj->Get(env.local(), sym4)
    3258             :             .ToLocalChecked()
    3259             :             ->Equals(env.local(), v8::Integer::New(isolate, 314))
    3260             :             .FromJust());
    3261          18 :   CHECK(obj->Delete(env.local(), v8_str("accessor_native")).FromJust());
    3262             : 
    3263             :   // Add another property and delete it afterwards to force the object in
    3264             :   // slow case.
    3265          18 :   CHECK(
    3266             :       obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
    3267          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3268             :                      .ToLocalChecked()
    3269             :                      ->Int32Value(env.local())
    3270             :                      .FromJust());
    3271          24 :   CHECK_EQ(2008, obj->Get(env.local(), sym2)
    3272             :                      .ToLocalChecked()
    3273             :                      ->Int32Value(env.local())
    3274             :                      .FromJust());
    3275          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3276             :                      .ToLocalChecked()
    3277             :                      ->Int32Value(env.local())
    3278             :                      .FromJust());
    3279          12 :   CHECK_EQ(2u,
    3280             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3281             : 
    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          12 :   CHECK(obj->Delete(env.local(), sym2).FromJust());
    3287          12 :   CHECK(obj->Has(env.local(), sym1).FromJust());
    3288          12 :   CHECK(!obj->Has(env.local(), sym2).FromJust());
    3289          12 :   CHECK(obj->Has(env.local(), sym3).FromJust());
    3290          18 :   CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
    3291          24 :   CHECK_EQ(2002, obj->Get(env.local(), sym1)
    3292             :                      .ToLocalChecked()
    3293             :                      ->Int32Value(env.local())
    3294             :                      .FromJust());
    3295          30 :   CHECK(obj->Get(env.local(), sym3)
    3296             :             .ToLocalChecked()
    3297             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3298             :             .FromJust());
    3299          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3300             :             .ToLocalChecked()
    3301             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3302             :             .FromJust());
    3303          12 :   CHECK_EQ(2u,
    3304             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3305             : 
    3306             :   // Symbol properties are inherited.
    3307           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3308          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3309          12 :   CHECK(child->Has(env.local(), sym1).FromJust());
    3310          24 :   CHECK_EQ(2002, child->Get(env.local(), sym1)
    3311             :                      .ToLocalChecked()
    3312             :                      ->Int32Value(env.local())
    3313             :                      .FromJust());
    3314          30 :   CHECK(obj->Get(env.local(), sym3)
    3315             :             .ToLocalChecked()
    3316             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3317             :             .FromJust());
    3318          30 :   CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
    3319             :             .ToLocalChecked()
    3320             :             ->Equals(env.local(), v8::Integer::New(isolate, 42))
    3321             :             .FromJust());
    3322          12 :   CHECK_EQ(0u,
    3323           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3324           6 : }
    3325             : 
    3326             : 
    3327       25881 : THREADED_TEST(SymbolTemplateProperties) {
    3328           6 :   LocalContext env;
    3329           6 :   v8::Isolate* isolate = env->GetIsolate();
    3330          12 :   v8::HandleScope scope(isolate);
    3331           6 :   v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
    3332           6 :   v8::Local<v8::Name> name = v8::Symbol::New(isolate);
    3333           6 :   CHECK(!name.IsEmpty());
    3334          18 :   foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
    3335             :   v8::Local<v8::Object> new_instance =
    3336          18 :       foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
    3337           6 :   CHECK(!new_instance.IsEmpty());
    3338          18 :   CHECK(new_instance->Has(env.local(), name).FromJust());
    3339           6 : }
    3340             : 
    3341             : 
    3342       25881 : THREADED_TEST(PrivatePropertiesOnProxies) {
    3343           6 :   LocalContext env;
    3344           6 :   v8::Isolate* isolate = env->GetIsolate();
    3345          12 :   v8::HandleScope scope(isolate);
    3346             : 
    3347           6 :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
    3348           6 :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
    3349             : 
    3350             :   v8::Local<v8::Proxy> proxy =
    3351           6 :       v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
    3352             : 
    3353           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3354             :   v8::Local<v8::Private> priv2 =
    3355           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3356             : 
    3357           6 :   CcTest::CollectAllGarbage();
    3358             : 
    3359          30 :   CHECK(priv2->Name()
    3360             :             ->Equals(env.local(),
    3361             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3362             :                                              v8::NewStringType::kNormal)
    3363             :                          .ToLocalChecked())
    3364             :             .FromJust());
    3365             : 
    3366             :   // Make sure delete of a non-existent private symbol property works.
    3367          12 :   proxy->DeletePrivate(env.local(), priv1).FromJust();
    3368          12 :   CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
    3369             : 
    3370          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3371             :             .FromJust());
    3372          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3373          18 :   CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
    3374             :                      .ToLocalChecked()
    3375             :                      ->Int32Value(env.local())
    3376             :                      .FromJust());
    3377          18 :   CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3378             :             .FromJust());
    3379          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3380          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3381             :                      .ToLocalChecked()
    3382             :                      ->Int32Value(env.local())
    3383             :                      .FromJust());
    3384             : 
    3385          12 :   CHECK_EQ(0u,
    3386             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3387             :   unsigned num_props =
    3388          12 :       proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3389          24 :   CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
    3390             :                                     isolate, "bla", v8::NewStringType::kNormal)
    3391             :                                     .ToLocalChecked(),
    3392             :                    v8::Integer::New(isolate, 20))
    3393             :             .FromJust());
    3394          12 :   CHECK_EQ(1u,
    3395             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3396          12 :   CHECK_EQ(num_props + 1,
    3397             :            proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3398             : 
    3399           6 :   CcTest::CollectAllGarbage();
    3400             : 
    3401             :   // Add another property and delete it afterwards to force the object in
    3402             :   // slow case.
    3403          18 :   CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3404             :             .FromJust());
    3405          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3406             :                      .ToLocalChecked()
    3407             :                      ->Int32Value(env.local())
    3408             :                      .FromJust());
    3409          18 :   CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
    3410             :                      .ToLocalChecked()
    3411             :                      ->Int32Value(env.local())
    3412             :                      .FromJust());
    3413          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3414             :                      .ToLocalChecked()
    3415             :                      ->Int32Value(env.local())
    3416             :                      .FromJust());
    3417          12 :   CHECK_EQ(1u,
    3418             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3419             : 
    3420          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3421          12 :   CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
    3422          12 :   CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
    3423          12 :   CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
    3424          12 :   CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
    3425          18 :   CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
    3426             :                      .ToLocalChecked()
    3427             :                      ->Int32Value(env.local())
    3428             :                      .FromJust());
    3429          12 :   CHECK_EQ(1u,
    3430             :            proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3431             : 
    3432             :   // Private properties are not inherited (for the time being).
    3433           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3434          12 :   CHECK(child->SetPrototype(env.local(), proxy).FromJust());
    3435          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3436          12 :   CHECK_EQ(0u,
    3437           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3438           6 : }
    3439             : 
    3440             : 
    3441       25881 : THREADED_TEST(PrivateProperties) {
    3442           6 :   LocalContext env;
    3443           6 :   v8::Isolate* isolate = env->GetIsolate();
    3444          12 :   v8::HandleScope scope(isolate);
    3445             : 
    3446           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3447           6 :   v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
    3448             :   v8::Local<v8::Private> priv2 =
    3449           6 :       v8::Private::New(isolate, v8_str("my-private"));
    3450             : 
    3451           6 :   CcTest::CollectAllGarbage();
    3452             : 
    3453          30 :   CHECK(priv2->Name()
    3454             :             ->Equals(env.local(),
    3455             :                      v8::String::NewFromUtf8(isolate, "my-private",
    3456             :                                              v8::NewStringType::kNormal)
    3457             :                          .ToLocalChecked())
    3458             :             .FromJust());
    3459             : 
    3460             :   // Make sure delete of a non-existent private symbol property works.
    3461          12 :   obj->DeletePrivate(env.local(), priv1).FromJust();
    3462          12 :   CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
    3463             : 
    3464          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
    3465             :             .FromJust());
    3466          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3467          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
    3468             :                      .ToLocalChecked()
    3469             :                      ->Int32Value(env.local())
    3470             :                      .FromJust());
    3471          18 :   CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
    3472             :             .FromJust());
    3473          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3474          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3475             :                      .ToLocalChecked()
    3476             :                      ->Int32Value(env.local())
    3477             :                      .FromJust());
    3478             : 
    3479          12 :   CHECK_EQ(0u,
    3480             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3481             :   unsigned num_props =
    3482          12 :       obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
    3483          24 :   CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
    3484             :                                   isolate, "bla", v8::NewStringType::kNormal)
    3485             :                                   .ToLocalChecked(),
    3486             :                  v8::Integer::New(isolate, 20))
    3487             :             .FromJust());
    3488          12 :   CHECK_EQ(1u,
    3489             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3490          12 :   CHECK_EQ(num_props + 1,
    3491             :            obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
    3492             : 
    3493           6 :   CcTest::CollectAllGarbage();
    3494             : 
    3495             :   // Add another property and delete it afterwards to force the object in
    3496             :   // slow case.
    3497          18 :   CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
    3498             :             .FromJust());
    3499          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3500             :                      .ToLocalChecked()
    3501             :                      ->Int32Value(env.local())
    3502             :                      .FromJust());
    3503          18 :   CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
    3504             :                      .ToLocalChecked()
    3505             :                      ->Int32Value(env.local())
    3506             :                      .FromJust());
    3507          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3508             :                      .ToLocalChecked()
    3509             :                      ->Int32Value(env.local())
    3510             :                      .FromJust());
    3511          12 :   CHECK_EQ(1u,
    3512             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3513             : 
    3514          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3515          12 :   CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
    3516          12 :   CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
    3517          12 :   CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
    3518          12 :   CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
    3519          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
    3520             :                      .ToLocalChecked()
    3521             :                      ->Int32Value(env.local())
    3522             :                      .FromJust());
    3523          12 :   CHECK_EQ(1u,
    3524             :            obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3525             : 
    3526             :   // Private properties are not inherited (for the time being).
    3527           6 :   v8::Local<v8::Object> child = v8::Object::New(isolate);
    3528          12 :   CHECK(child->SetPrototype(env.local(), obj).FromJust());
    3529          12 :   CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
    3530          12 :   CHECK_EQ(0u,
    3531           6 :            child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
    3532           6 : }
    3533             : 
    3534             : 
    3535       25881 : THREADED_TEST(GlobalSymbols) {
    3536           6 :   LocalContext env;
    3537           6 :   v8::Isolate* isolate = env->GetIsolate();
    3538          12 :   v8::HandleScope scope(isolate);
    3539             : 
    3540           6 :   v8::Local<String> name = v8_str("my-symbol");
    3541           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3542           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3543           6 :   CHECK(glob2->SameValue(glob));
    3544             : 
    3545           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3546           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3547           6 :   CHECK(glob_api2->SameValue(glob_api));
    3548           6 :   CHECK(!glob_api->SameValue(glob));
    3549             : 
    3550           6 :   v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
    3551           6 :   CHECK(!sym->SameValue(glob));
    3552             : 
    3553             :   CompileRun("var sym2 = Symbol.for('my-symbol')");
    3554             :   v8::Local<Value> sym2 =
    3555          30 :       env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
    3556           6 :   CHECK(sym2->SameValue(glob));
    3557          12 :   CHECK(!sym2->SameValue(glob_api));
    3558           6 : }
    3559             : 
    3560       25881 : THREADED_TEST(GlobalSymbolsNoContext) {
    3561           6 :   v8::Isolate* isolate = CcTest::isolate();
    3562           6 :   v8::HandleScope scope(isolate);
    3563             : 
    3564           6 :   v8::Local<String> name = v8_str("my-symbol");
    3565           6 :   v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
    3566           6 :   v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
    3567           6 :   CHECK(glob2->SameValue(glob));
    3568             : 
    3569           6 :   v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
    3570           6 :   v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
    3571           6 :   CHECK(glob_api2->SameValue(glob_api));
    3572           6 :   CHECK(!glob_api->SameValue(glob));
    3573           6 : }
    3574             : 
    3575          60 : static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
    3576             :                                  const char* name) {
    3577          60 :   LocalContext env;
    3578          60 :   v8::Isolate* isolate = env->GetIsolate();
    3579         120 :   v8::HandleScope scope(isolate);
    3580             : 
    3581          60 :   v8::Local<v8::Symbol> symbol = getter(isolate);
    3582         120 :   std::string script = std::string("var sym = ") + name;
    3583             :   CompileRun(script.c_str());
    3584             :   v8::Local<Value> value =
    3585         300 :       env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
    3586             : 
    3587          60 :   CHECK(!value.IsEmpty());
    3588          60 :   CHECK(!symbol.IsEmpty());
    3589         120 :   CHECK(value->SameValue(symbol));
    3590          60 : }
    3591             : 
    3592             : 
    3593       25881 : THREADED_TEST(WellKnownSymbols) {
    3594           6 :   CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
    3595           6 :   CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
    3596           6 :   CheckWellKnownSymbol(v8::Symbol::GetHasInstance, "Symbol.hasInstance");
    3597             :   CheckWellKnownSymbol(v8::Symbol::GetIsConcatSpreadable,
    3598           6 :                        "Symbol.isConcatSpreadable");
    3599           6 :   CheckWellKnownSymbol(v8::Symbol::GetMatch, "Symbol.match");
    3600           6 :   CheckWellKnownSymbol(v8::Symbol::GetReplace, "Symbol.replace");
    3601           6 :   CheckWellKnownSymbol(v8::Symbol::GetSearch, "Symbol.search");
    3602           6 :   CheckWellKnownSymbol(v8::Symbol::GetSplit, "Symbol.split");
    3603           6 :   CheckWellKnownSymbol(v8::Symbol::GetToPrimitive, "Symbol.toPrimitive");
    3604           6 :   CheckWellKnownSymbol(v8::Symbol::GetToStringTag, "Symbol.toStringTag");
    3605           6 : }
    3606             : 
    3607             : 
    3608       25881 : THREADED_TEST(GlobalPrivates) {
    3609           6 :   i::FLAG_allow_natives_syntax = true;
    3610           6 :   LocalContext env;
    3611           6 :   v8::Isolate* isolate = env->GetIsolate();
    3612          12 :   v8::HandleScope scope(isolate);
    3613             : 
    3614           6 :   v8::Local<String> name = v8_str("my-private");
    3615           6 :   v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
    3616           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    3617          18 :   CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
    3618             :             .FromJust());
    3619             : 
    3620           6 :   v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
    3621          12 :   CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
    3622             : 
    3623           6 :   v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
    3624          12 :   CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
    3625             : 
    3626             :   CompileRun("var intern = %CreatePrivateSymbol('my-private')");
    3627             :   v8::Local<Value> intern =
    3628          30 :       env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
    3629          18 :   CHECK(!obj->Has(env.local(), intern).FromJust());
    3630           6 : }
    3631             : 
    3632             : 
    3633             : class ScopedArrayBufferContents {
    3634             :  public:
    3635             :   explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
    3636          36 :       : contents_(contents) {}
    3637          36 :   ~ScopedArrayBufferContents() { free(contents_.AllocationBase()); }
    3638             :   void* Data() const { return contents_.Data(); }
    3639             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3640             : 
    3641             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3642             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3643             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3644             :     return contents_.AllocationMode();
    3645             :   }
    3646             : 
    3647             :  private:
    3648             :   const v8::ArrayBuffer::Contents contents_;
    3649             : };
    3650             : 
    3651             : template <typename T>
    3652         282 : static void CheckInternalFieldsAreZero(v8::Local<T> value) {
    3653         282 :   CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
    3654         564 :   for (int i = 0; i < value->InternalFieldCount(); i++) {
    3655        1692 :     CHECK_EQ(0, value->GetInternalField(i)
    3656             :                     ->Int32Value(CcTest::isolate()->GetCurrentContext())
    3657             :                     .FromJust());
    3658             :   }
    3659         282 : }
    3660             : 
    3661             : 
    3662       25881 : THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
    3663           6 :   LocalContext env;
    3664           6 :   v8::Isolate* isolate = env->GetIsolate();
    3665          12 :   v8::HandleScope handle_scope(isolate);
    3666             : 
    3667           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
    3668           6 :   CheckInternalFieldsAreZero(ab);
    3669           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3670           6 :   CHECK(!ab->IsExternal());
    3671           6 :   CcTest::CollectAllGarbage();
    3672             : 
    3673          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3674           6 :   CHECK(ab->IsExternal());
    3675             : 
    3676           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3677             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3678           6 :   CHECK_NOT_NULL(data);
    3679          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3680             : 
    3681             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    3682          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3683             : 
    3684             :   result = CompileRun(
    3685             :       "var u8 = new Uint8Array(ab);"
    3686             :       "u8[0] = 0xFF;"
    3687             :       "u8[1] = 0xAA;"
    3688             :       "u8.length");
    3689          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    3690          12 :   CHECK_EQ(0xFF, data[0]);
    3691          12 :   CHECK_EQ(0xAA, data[1]);
    3692           6 :   data[0] = 0xCC;
    3693           6 :   data[1] = 0x11;
    3694             :   result = CompileRun("u8[0] + u8[1]");
    3695          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3696           6 : }
    3697             : 
    3698             : 
    3699       25881 : THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
    3700           6 :   LocalContext env;
    3701           6 :   v8::Isolate* isolate = env->GetIsolate();
    3702          12 :   v8::HandleScope handle_scope(isolate);
    3703             : 
    3704             : 
    3705             :   v8::Local<v8::Value> result = CompileRun(
    3706             :       "var ab1 = new ArrayBuffer(2);"
    3707             :       "var u8_a = new Uint8Array(ab1);"
    3708             :       "u8_a[0] = 0xAA;"
    3709             :       "u8_a[1] = 0xFF; u8_a.buffer");
    3710             :   Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
    3711           6 :   CheckInternalFieldsAreZero(ab1);
    3712           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    3713           6 :   CHECK(!ab1->IsExternal());
    3714          12 :   ScopedArrayBufferContents ab1_contents(ab1->Externalize());
    3715           6 :   CHECK(ab1->IsExternal());
    3716             : 
    3717             :   result = CompileRun("ab1.byteLength");
    3718          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    3719             :   result = CompileRun("u8_a[0]");
    3720          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    3721             :   result = CompileRun("u8_a[1]");
    3722          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3723             :   result = CompileRun(
    3724             :       "var u8_b = new Uint8Array(ab1);"
    3725             :       "u8_b[0] = 0xBB;"
    3726             :       "u8_a[0]");
    3727          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    3728             :   result = CompileRun("u8_b[1]");
    3729          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    3730             : 
    3731           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    3732             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    3733          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    3734          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    3735           6 :   ab1_data[0] = 0xCC;
    3736           6 :   ab1_data[1] = 0x11;
    3737             :   result = CompileRun("u8_a[0] + u8_a[1]");
    3738          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3739           6 : }
    3740             : 
    3741             : 
    3742       25881 : THREADED_TEST(ArrayBuffer_External) {
    3743           6 :   LocalContext env;
    3744           6 :   v8::Isolate* isolate = env->GetIsolate();
    3745          12 :   v8::HandleScope handle_scope(isolate);
    3746             : 
    3747             :   i::ScopedVector<uint8_t> my_data(100);
    3748             :   memset(my_data.start(), 0, 100);
    3749             :   Local<v8::ArrayBuffer> ab3 =
    3750           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3751           6 :   CheckInternalFieldsAreZero(ab3);
    3752           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    3753           6 :   CHECK(ab3->IsExternal());
    3754             : 
    3755          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    3756             : 
    3757             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    3758          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3759             : 
    3760             :   result = CompileRun(
    3761             :       "var u8_b = new Uint8Array(ab3);"
    3762             :       "u8_b[0] = 0xBB;"
    3763             :       "u8_b[1] = 0xCC;"
    3764             :       "u8_b.length");
    3765          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    3766          12 :   CHECK_EQ(0xBB, my_data[0]);
    3767          12 :   CHECK_EQ(0xCC, my_data[1]);
    3768           6 :   my_data[0] = 0xCC;
    3769           6 :   my_data[1] = 0x11;
    3770             :   result = CompileRun("u8_b[0] + u8_b[1]");
    3771          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    3772           6 : }
    3773             : 
    3774       25881 : THREADED_TEST(ArrayBuffer_DisableDetach) {
    3775           6 :   LocalContext env;
    3776           6 :   v8::Isolate* isolate = env->GetIsolate();
    3777          12 :   v8::HandleScope handle_scope(isolate);
    3778             : 
    3779             :   i::ScopedVector<uint8_t> my_data(100);
    3780             :   memset(my_data.start(), 0, 100);
    3781             :   Local<v8::ArrayBuffer> ab =
    3782           6 :       v8::ArrayBuffer::New(isolate, my_data.start(), 100);
    3783           6 :   CHECK(ab->IsDetachable());
    3784             : 
    3785             :   i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
    3786             :   buf->set_is_detachable(false);
    3787             : 
    3788          12 :   CHECK(!ab->IsDetachable());
    3789           6 : }
    3790             : 
    3791          12 : static void CheckDataViewIsDetached(v8::Local<v8::DataView> dv) {
    3792          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
    3793          12 :   CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
    3794          12 : }
    3795             : 
    3796         108 : static void CheckIsDetached(v8::Local<v8::TypedArray> ta) {
    3797         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
    3798         108 :   CHECK_EQ(0, static_cast<int>(ta->Length()));
    3799         108 :   CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
    3800         108 : }
    3801             : 
    3802          54 : static void CheckIsTypedArrayVarDetached(const char* name) {
    3803             :   i::ScopedVector<char> source(1024);
    3804             :   i::SNPrintF(source,
    3805             :               "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
    3806          54 :               name, name, name);
    3807          54 :   CHECK(CompileRun(source.start())->IsTrue());
    3808             :   v8::Local<v8::TypedArray> ta =
    3809          54 :       v8::Local<v8::TypedArray>::Cast(CompileRun(name));
    3810          54 :   CheckIsDetached(ta);
    3811          54 : }
    3812             : 
    3813             : template <typename TypedArray, int kElementSize>
    3814          54 : static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
    3815             :                                         int byteOffset, int length) {
    3816          54 :   v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
    3817          54 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
    3818          54 :   CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
    3819          54 :   CHECK_EQ(length, static_cast<int>(ta->Length()));
    3820          54 :   CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
    3821          54 :   return ta;
    3822             : }
    3823             : 
    3824       25881 : THREADED_TEST(ArrayBuffer_DetachingApi) {
    3825           6 :   LocalContext env;
    3826           6 :   v8::Isolate* isolate = env->GetIsolate();
    3827          12 :   v8::HandleScope handle_scope(isolate);
    3828             : 
    3829           6 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
    3830             : 
    3831             :   v8::Local<v8::Uint8Array> u8a =
    3832           6 :       CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
    3833             :   v8::Local<v8::Uint8ClampedArray> u8c =
    3834           6 :       CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
    3835             :   v8::Local<v8::Int8Array> i8a =
    3836           6 :       CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
    3837             : 
    3838             :   v8::Local<v8::Uint16Array> u16a =
    3839           6 :       CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
    3840             :   v8::Local<v8::Int16Array> i16a =
    3841           6 :       CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
    3842             : 
    3843             :   v8::Local<v8::Uint32Array> u32a =
    3844           6 :       CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
    3845             :   v8::Local<v8::Int32Array> i32a =
    3846           6 :       CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
    3847             : 
    3848             :   v8::Local<v8::Float32Array> f32a =
    3849           6 :       CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
    3850             :   v8::Local<v8::Float64Array> f64a =
    3851           6 :       CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
    3852             : 
    3853           6 :   v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
    3854           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
    3855           6 :   CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
    3856           6 :   CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
    3857             : 
    3858          12 :   ScopedArrayBufferContents contents(buffer->Externalize());
    3859           6 :   buffer->Detach();
    3860           6 :   CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
    3861           6 :   CheckIsDetached(u8a);
    3862           6 :   CheckIsDetached(u8c);
    3863           6 :   CheckIsDetached(i8a);
    3864           6 :   CheckIsDetached(u16a);
    3865           6 :   CheckIsDetached(i16a);
    3866           6 :   CheckIsDetached(u32a);
    3867           6 :   CheckIsDetached(i32a);
    3868           6 :   CheckIsDetached(f32a);
    3869           6 :   CheckIsDetached(f64a);
    3870          12 :   CheckDataViewIsDetached(dv);
    3871           6 : }
    3872             : 
    3873       25881 : THREADED_TEST(ArrayBuffer_DetachingScript) {
    3874           6 :   LocalContext env;
    3875           6 :   v8::Isolate* isolate = env->GetIsolate();
    3876          12 :   v8::HandleScope handle_scope(isolate);
    3877             : 
    3878             :   CompileRun(
    3879             :       "var ab = new ArrayBuffer(1024);"
    3880             :       "var u8a = new Uint8Array(ab, 1, 1023);"
    3881             :       "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
    3882             :       "var i8a = new Int8Array(ab, 1, 1023);"
    3883             :       "var u16a = new Uint16Array(ab, 2, 511);"
    3884             :       "var i16a = new Int16Array(ab, 2, 511);"
    3885             :       "var u32a = new Uint32Array(ab, 4, 255);"
    3886             :       "var i32a = new Int32Array(ab, 4, 255);"
    3887             :       "var f32a = new Float32Array(ab, 4, 255);"
    3888             :       "var f64a = new Float64Array(ab, 8, 127);"
    3889             :       "var dv = new DataView(ab, 1, 1023);");
    3890             : 
    3891             :   v8::Local<v8::ArrayBuffer> ab =
    3892             :       Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
    3893             : 
    3894           6 :   v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
    3895             : 
    3896          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3897           6 :   ab->Detach();
    3898           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3899           6 :   CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
    3900             : 
    3901           6 :   CheckIsTypedArrayVarDetached("u8a");
    3902           6 :   CheckIsTypedArrayVarDetached("u8c");
    3903           6 :   CheckIsTypedArrayVarDetached("i8a");
    3904           6 :   CheckIsTypedArrayVarDetached("u16a");
    3905           6 :   CheckIsTypedArrayVarDetached("i16a");
    3906           6 :   CheckIsTypedArrayVarDetached("u32a");
    3907           6 :   CheckIsTypedArrayVarDetached("i32a");
    3908           6 :   CheckIsTypedArrayVarDetached("f32a");
    3909           6 :   CheckIsTypedArrayVarDetached("f64a");
    3910             : 
    3911           6 :   CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
    3912          12 :   CheckDataViewIsDetached(dv);
    3913           6 : }
    3914             : 
    3915       25881 : THREADED_TEST(ArrayBuffer_AllocationInformation) {
    3916           6 :   LocalContext env;
    3917           6 :   v8::Isolate* isolate = env->GetIsolate();
    3918          12 :   v8::HandleScope handle_scope(isolate);
    3919             : 
    3920             :   const size_t ab_size = 1024;
    3921           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, ab_size);
    3922          12 :   ScopedArrayBufferContents contents(ab->Externalize());
    3923             : 
    3924             :   // Array buffers should have normal allocation mode.
    3925           6 :   CHECK_EQ(contents.AllocationMode(),
    3926             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
    3927             :   // The allocation must contain the buffer (normally they will be equal, but
    3928             :   // this is not required by the contract).
    3929           6 :   CHECK_NOT_NULL(contents.AllocationBase());
    3930             :   const uintptr_t alloc =
    3931           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
    3932           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
    3933           6 :   CHECK_LE(alloc, data);
    3934          12 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
    3935           6 : }
    3936             : 
    3937       25881 : THREADED_TEST(ArrayBuffer_ExternalizeEmpty) {
    3938           6 :   LocalContext env;
    3939           6 :   v8::Isolate* isolate = env->GetIsolate();
    3940          12 :   v8::HandleScope handle_scope(isolate);
    3941             : 
    3942           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 0);
    3943           6 :   CheckInternalFieldsAreZero(ab);
    3944           6 :   CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
    3945           6 :   CHECK(!ab->IsExternal());
    3946             : 
    3947             :   // Externalize the buffer (taking ownership of the backing store memory).
    3948          12 :   ScopedArrayBufferContents ab_contents(ab->Externalize());
    3949             : 
    3950           6 :   Local<v8::Uint8Array> u8a = v8::Uint8Array::New(ab, 0, 0);
    3951             :   // Calling Buffer() will materialize the ArrayBuffer (transitioning it from
    3952             :   // on-heap to off-heap if need be). This should not affect whether it is
    3953             :   // marked as is_external or not.
    3954           6 :   USE(u8a->Buffer());
    3955             : 
    3956          12 :   CHECK(ab->IsExternal());
    3957           6 : }
    3958             : 
    3959             : class ScopedSharedArrayBufferContents {
    3960             :  public:
    3961             :   explicit ScopedSharedArrayBufferContents(
    3962             :       const v8::SharedArrayBuffer::Contents& contents)
    3963          18 :       : contents_(contents) {}
    3964          18 :   ~ScopedSharedArrayBufferContents() { free(contents_.AllocationBase()); }
    3965             :   void* Data() const { return contents_.Data(); }
    3966             :   size_t ByteLength() const { return contents_.ByteLength(); }
    3967             : 
    3968             :   void* AllocationBase() const { return contents_.AllocationBase(); }
    3969             :   size_t AllocationLength() const { return contents_.AllocationLength(); }
    3970             :   v8::ArrayBuffer::Allocator::AllocationMode AllocationMode() const {
    3971             :     return contents_.AllocationMode();
    3972             :   }
    3973             : 
    3974             :  private:
    3975             :   const v8::SharedArrayBuffer::Contents contents_;
    3976             : };
    3977             : 
    3978             : 
    3979       25881 : THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
    3980           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    3981           6 :   LocalContext env;
    3982           6 :   v8::Isolate* isolate = env->GetIsolate();
    3983          12 :   v8::HandleScope handle_scope(isolate);
    3984             : 
    3985           6 :   Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
    3986           6 :   CheckInternalFieldsAreZero(ab);
    3987           6 :   CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
    3988           6 :   CHECK(!ab->IsExternal());
    3989           6 :   CcTest::CollectAllGarbage();
    3990             : 
    3991          12 :   ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
    3992           6 :   CHECK(ab->IsExternal());
    3993             : 
    3994           6 :   CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
    3995             :   uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
    3996           6 :   CHECK_NOT_NULL(data);
    3997          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
    3998             : 
    3999             :   v8::Local<v8::Value> result = CompileRun("ab.byteLength");
    4000          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    4001             : 
    4002             :   result = CompileRun(
    4003             :       "var u8 = new Uint8Array(ab);"
    4004             :       "u8[0] = 0xFF;"
    4005             :       "u8[1] = 0xAA;"
    4006             :       "u8.length");
    4007          12 :   CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
    4008          12 :   CHECK_EQ(0xFF, data[0]);
    4009          12 :   CHECK_EQ(0xAA, data[1]);
    4010           6 :   data[0] = 0xCC;
    4011           6 :   data[1] = 0x11;
    4012             :   result = CompileRun("u8[0] + u8[1]");
    4013          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4014           6 : }
    4015             : 
    4016             : 
    4017       25881 : THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
    4018           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4019           6 :   LocalContext env;
    4020           6 :   v8::Isolate* isolate = env->GetIsolate();
    4021          12 :   v8::HandleScope handle_scope(isolate);
    4022             : 
    4023             : 
    4024             :   v8::Local<v8::Value> result = CompileRun(
    4025             :       "var ab1 = new SharedArrayBuffer(2);"
    4026             :       "var u8_a = new Uint8Array(ab1);"
    4027             :       "u8_a[0] = 0xAA;"
    4028             :       "u8_a[1] = 0xFF; u8_a.buffer");
    4029             :   Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
    4030           6 :   CheckInternalFieldsAreZero(ab1);
    4031           6 :   CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
    4032           6 :   CHECK(!ab1->IsExternal());
    4033          12 :   ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
    4034           6 :   CHECK(ab1->IsExternal());
    4035             : 
    4036             :   result = CompileRun("ab1.byteLength");
    4037          12 :   CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
    4038             :   result = CompileRun("u8_a[0]");
    4039          12 :   CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
    4040             :   result = CompileRun("u8_a[1]");
    4041          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    4042             :   result = CompileRun(
    4043             :       "var u8_b = new Uint8Array(ab1);"
    4044             :       "u8_b[0] = 0xBB;"
    4045             :       "u8_a[0]");
    4046          12 :   CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
    4047             :   result = CompileRun("u8_b[1]");
    4048          12 :   CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
    4049             : 
    4050           6 :   CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
    4051             :   uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
    4052          12 :   CHECK_EQ(0xBB, ab1_data[0]);
    4053          12 :   CHECK_EQ(0xFF, ab1_data[1]);
    4054           6 :   ab1_data[0] = 0xCC;
    4055           6 :   ab1_data[1] = 0x11;
    4056             :   result = CompileRun("u8_a[0] + u8_a[1]");
    4057          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4058           6 : }
    4059             : 
    4060             : 
    4061       25881 : THREADED_TEST(SharedArrayBuffer_External) {
    4062           6 :   i::FLAG_harmony_sharedarraybuffer = true;
    4063           6 :   LocalContext env;
    4064           6 :   v8::Isolate* isolate = env->GetIsolate();
    4065          12 :   v8::HandleScope handle_scope(isolate);
    4066             : 
    4067             :   i::ScopedVector<uint8_t> my_data(100);
    4068             :   memset(my_data.start(), 0, 100);
    4069             :   Local<v8::SharedArrayBuffer> ab3 =
    4070           6 :       v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
    4071           6 :   CheckInternalFieldsAreZero(ab3);
    4072           6 :   CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
    4073           6 :   CHECK(ab3->IsExternal());
    4074             : 
    4075          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
    4076             : 
    4077             :   v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
    4078          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    4079             : 
    4080             :   result = CompileRun(
    4081             :       "var u8_b = new Uint8Array(ab3);"
    4082             :       "u8_b[0] = 0xBB;"
    4083             :       "u8_b[1] = 0xCC;"
    4084             :       "u8_b.length");
    4085          12 :   CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
    4086          12 :   CHECK_EQ(0xBB, my_data[0]);
    4087          12 :   CHECK_EQ(0xCC, my_data[1]);
    4088           6 :   my_data[0] = 0xCC;
    4089           6 :   my_data[1] = 0x11;
    4090             :   result = CompileRun("u8_b[0] + u8_b[1]");
    4091          18 :   CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
    4092           6 : }
    4093             : 
    4094             : 
    4095       25881 : THREADED_TEST(HiddenProperties) {
    4096           6 :   LocalContext env;
    4097           6 :   v8::Isolate* isolate = env->GetIsolate();
    4098          12 :   v8::HandleScope scope(isolate);
    4099             : 
    4100           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4101             :   v8::Local<v8::Private> key =
    4102           6 :       v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
    4103           6 :   v8::Local<v8::String> empty = v8_str("");
    4104           6 :   v8::Local<v8::String> prop_name = v8_str("prop_name");
    4105             : 
    4106           6 :   CcTest::CollectAllGarbage();
    4107             : 
    4108             :   // Make sure delete of a non-existent hidden value works
    4109          12 :   obj->DeletePrivate(env.local(), key).FromJust();
    4110             : 
    4111          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
    4112             :             .FromJust());
    4113          18 :   CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
    4114             :                      .ToLocalChecked()
    4115             :                      ->Int32Value(env.local())
    4116             :                      .FromJust());
    4117          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4118             :             .FromJust());
    4119          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4120             :                      .ToLocalChecked()
    4121             :                      ->Int32Value(env.local())
    4122             :                      .FromJust());
    4123             : 
    4124           6 :   CcTest::CollectAllGarbage();
    4125             : 
    4126             :   // Make sure we do not find the hidden property.
    4127          12 :   CHECK(!obj->Has(env.local(), empty).FromJust());
    4128          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4129             :                      .ToLocalChecked()
    4130             :                      ->Int32Value(env.local())
    4131             :                      .FromJust());
    4132          12 :   CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
    4133          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4134             :                      .ToLocalChecked()
    4135             :                      ->Int32Value(env.local())
    4136             :                      .FromJust());
    4137          18 :   CHECK(
    4138             :       obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
    4139          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4140             :                      .ToLocalChecked()
    4141             :                      ->Int32Value(env.local())
    4142             :                      .FromJust());
    4143          24 :   CHECK_EQ(2003, obj->Get(env.local(), empty)
    4144             :                      .ToLocalChecked()
    4145             :                      ->Int32Value(env.local())
    4146             :                      .FromJust());
    4147             : 
    4148           6 :   CcTest::CollectAllGarbage();
    4149             : 
    4150             :   // Add another property and delete it afterwards to force the object in
    4151             :   // slow case.
    4152          18 :   CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
    4153             :             .FromJust());
    4154          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4155             :                      .ToLocalChecked()
    4156             :                      ->Int32Value(env.local())
    4157             :                      .FromJust());
    4158          24 :   CHECK_EQ(2008, obj->Get(env.local(), prop_name)
    4159             :                      .ToLocalChecked()
    4160             :                      ->Int32Value(env.local())
    4161             :                      .FromJust());
    4162          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4163             :                      .ToLocalChecked()
    4164             :                      ->Int32Value(env.local())
    4165             :                      .FromJust());
    4166          12 :   CHECK(obj->Delete(env.local(), prop_name).FromJust());
    4167          18 :   CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
    4168             :                      .ToLocalChecked()
    4169             :                      ->Int32Value(env.local())
    4170             :                      .FromJust());
    4171             : 
    4172           6 :   CcTest::CollectAllGarbage();
    4173             : 
    4174          18 :   CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
    4175             :             .FromJust());
    4176          12 :   CHECK(obj->DeletePrivate(env.local(), key).FromJust());
    4177          18 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4178           6 : }
    4179             : 
    4180             : 
    4181       25881 : THREADED_TEST(Regress97784) {
    4182             :   // Regression test for crbug.com/97784
    4183             :   // Messing with the Object.prototype should not have effect on
    4184             :   // hidden properties.
    4185           6 :   LocalContext env;
    4186          12 :   v8::HandleScope scope(env->GetIsolate());
    4187             : 
    4188           6 :   v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
    4189             :   v8::Local<v8::Private> key =
    4190          12 :       v8::Private::New(env->GetIsolate(), v8_str("hidden"));
    4191             : 
    4192             :   CompileRun(
    4193             :       "set_called = false;"
    4194             :       "Object.defineProperty("
    4195             :       "    Object.prototype,"
    4196             :       "    'hidden',"
    4197             :       "    {get: function() { return 45; },"
    4198             :       "     set: function() { set_called = true; }})");
    4199             : 
    4200          12 :   CHECK(!obj->HasPrivate(env.local(), key).FromJust());
    4201             :   // Make sure that the getter and setter from Object.prototype is not invoked.
    4202             :   // If it did we would have full access to the hidden properties in
    4203             :   // the accessor.
    4204          18 :   CHECK(
    4205             :       obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
    4206             :           .FromJust());
    4207             :   ExpectFalse("set_called");
    4208          18 :   CHECK_EQ(42, obj->GetPrivate(env.local(), key)
    4209             :                    .ToLocalChecked()
    4210             :                    ->Int32Value(env.local())
    4211           6 :                    .FromJust());
    4212           6 : }
    4213             : 
    4214             : 
    4215       25881 : THREADED_TEST(External) {
    4216           6 :   v8::HandleScope scope(CcTest::isolate());
    4217           6 :   int x = 3;
    4218           6 :   Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
    4219          12 :   LocalContext env;
    4220          30 :   CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
    4221             :   Local<Value> reext_obj = CompileRun("this.ext");
    4222             :   v8::Local<v8::External> reext = reext_obj.As<v8::External>();
    4223           6 :   int* ptr = static_cast<int*>(reext->Value());
    4224           6 :   CHECK_EQ(3, x);
    4225           6 :   *ptr = 10;
    4226           6 :   CHECK_EQ(x, 10);
    4227             : 
    4228             :   {
    4229             :     i::Handle<i::Object> obj = v8::Utils::OpenHandle(*ext);
    4230          18 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4231           6 :     CHECK(ext->IsExternal());
    4232           6 :     CHECK(!CompileRun("new Set().add(this.ext)").IsEmpty());
    4233          18 :     CHECK_EQ(i::HeapObject::cast(*obj)->map(), CcTest::heap()->external_map());
    4234           6 :     CHECK(ext->IsExternal());
    4235             :   }
    4236             : 
    4237             :   // Make sure unaligned pointers are wrapped properly.
    4238           6 :   char* data = i::StrDup("0123456789");
    4239           6 :   Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
    4240           6 :   Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
    4241           6 :   Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
    4242           6 :   Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
    4243             : 
    4244           6 :   char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
    4245           6 :   CHECK_EQ('0', *char_ptr);
    4246           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
    4247           6 :   CHECK_EQ('1', *char_ptr);
    4248           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
    4249           6 :   CHECK_EQ('2', *char_ptr);
    4250           6 :   char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
    4251           6 :   CHECK_EQ('3', *char_ptr);
    4252           6 :   i::DeleteArray(data);
    4253           6 : }
    4254             : 
    4255             : 
    4256       25881 : THREADED_TEST(GlobalHandle) {
    4257           6 :   v8::Isolate* isolate = CcTest::isolate();
    4258             :   v8::Persistent<String> global;
    4259             :   {
    4260           6 :     v8::HandleScope scope(isolate);
    4261          12 :     global.Reset(isolate, v8_str("str"));
    4262             :   }
    4263             :   {
    4264           6 :     v8::HandleScope scope(isolate);
    4265           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4266             :   }
    4267             :   global.Reset();
    4268             :   {
    4269           6 :     v8::HandleScope scope(isolate);
    4270          12 :     global.Reset(isolate, v8_str("str"));
    4271             :   }
    4272             :   {
    4273           6 :     v8::HandleScope scope(isolate);
    4274           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4275             :   }
    4276             :   global.Reset();
    4277           6 : }
    4278             : 
    4279             : 
    4280       25881 : THREADED_TEST(ResettingGlobalHandle) {
    4281          12 :   v8::Isolate* isolate = CcTest::isolate();
    4282             :   v8::Persistent<String> global;
    4283             :   {
    4284           6 :     v8::HandleScope scope(isolate);
    4285          12 :     global.Reset(isolate, v8_str("str"));
    4286             :   }
    4287          18 :   v8::internal::GlobalHandles* global_handles =
    4288             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4289             :   size_t initial_handle_count = global_handles->handles_count();
    4290             :   {
    4291           6 :     v8::HandleScope scope(isolate);
    4292           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4293             :   }
    4294             :   {
    4295           6 :     v8::HandleScope scope(isolate);
    4296          12 :     global.Reset(isolate, v8_str("longer"));
    4297             :   }
    4298           6 :   CHECK_EQ(global_handles->handles_count(), initial_handle_count);
    4299             :   {
    4300           6 :     v8::HandleScope scope(isolate);
    4301           6 :     CHECK_EQ(6, v8::Local<String>::New(isolate, global)->Length());
    4302             :   }
    4303             :   global.Reset();
    4304          12 :   CHECK_EQ(global_handles->handles_count(), initial_handle_count - 1);
    4305           6 : }
    4306             : 
    4307             : 
    4308       25881 : THREADED_TEST(ResettingGlobalHandleToEmpty) {
    4309          12 :   v8::Isolate* isolate = CcTest::isolate();
    4310             :   v8::Persistent<String> global;
    4311             :   {
    4312           6 :     v8::HandleScope scope(isolate);
    4313          12 :     global.Reset(isolate, v8_str("str"));
    4314             :   }
    4315          12 :   v8::internal::GlobalHandles* global_handles =
    4316             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4317             :   size_t initial_handle_count = global_handles->handles_count();
    4318             :   {
    4319           6 :     v8::HandleScope scope(isolate);
    4320           6 :     CHECK_EQ(3, v8::Local<String>::New(isolate, global)->Length());
    4321             :   }
    4322             :   {
    4323           6 :     v8::HandleScope scope(isolate);
    4324             :     Local<String> empty;
    4325           6 :     global.Reset(isolate, empty);
    4326             :   }
    4327           6 :   CHECK(global.IsEmpty());
    4328          12 :   CHECK_EQ(global_handles->handles_count(), initial_handle_count - 1);
    4329           6 : }
    4330             : 
    4331             : 
    4332             : template <class T>
    4333             : static v8::Global<T> PassUnique(v8::Global<T> unique) {
    4334             :   return unique.Pass();
    4335             : }
    4336             : 
    4337             : 
    4338             : template <class T>
    4339           6 : static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
    4340             :                                   const v8::Persistent<T>& global) {
    4341             :   v8::Global<String> unique(isolate, global);
    4342           6 :   return unique.Pass();
    4343             : }
    4344             : 
    4345             : 
    4346       25881 : THREADED_TEST(Global) {
    4347          12 :   v8::Isolate* isolate = CcTest::isolate();
    4348             :   v8::Persistent<String> global;
    4349             :   {
    4350           6 :     v8::HandleScope scope(isolate);
    4351          12 :     global.Reset(isolate, v8_str("str"));
    4352             :   }
    4353          48 :   v8::internal::GlobalHandles* global_handles =
    4354             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4355             :   size_t initial_handle_count = global_handles->handles_count();
    4356             :   {
    4357             :     v8::Global<String> unique(isolate, global);
    4358           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4359             :     // Test assignment via Pass
    4360             :     {
    4361             :       v8::Global<String> copy = unique.Pass();
    4362           6 :       CHECK(unique.IsEmpty());
    4363           6 :       CHECK(copy == global);
    4364           6 :       CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4365           6 :       unique = copy.Pass();
    4366             :     }
    4367             :     // Test ctor via Pass
    4368             :     {
    4369             :       v8::Global<String> copy(unique.Pass());
    4370           6 :       CHECK(unique.IsEmpty());
    4371           6 :       CHECK(copy == global);
    4372           6 :       CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4373           6 :       unique = copy.Pass();
    4374             :     }
    4375             :     // Test pass through function call
    4376             :     {
    4377           6 :       v8::Global<String> copy = PassUnique(unique.Pass());
    4378           6 :       CHECK(unique.IsEmpty());
    4379           6 :       CHECK(copy == global);
    4380           6 :       CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4381           6 :       unique = copy.Pass();
    4382             :     }
    4383           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4384             :   }
    4385             :   // Test pass from function call
    4386             :   {
    4387           6 :     v8::Global<String> unique = ReturnUnique(isolate, global);
    4388           6 :     CHECK(unique == global);
    4389           6 :     CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4390             :   }
    4391           6 :   CHECK_EQ(initial_handle_count, global_handles->handles_count());
    4392             :   global.Reset();
    4393           6 : }
    4394             : 
    4395             : 
    4396             : namespace {
    4397             : 
    4398             : class TwoPassCallbackData;
    4399             : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4400             : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
    4401             : 
    4402             : 
    4403             : class TwoPassCallbackData {
    4404             :  public:
    4405         215 :   TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
    4406             :       : first_pass_called_(false),
    4407             :         second_pass_called_(false),
    4408             :         trigger_gc_(false),
    4409         430 :         instance_counter_(instance_counter) {
    4410         215 :     HandleScope scope(isolate);
    4411             :     i::ScopedVector<char> buffer(40);
    4412         215 :     i::SNPrintF(buffer, "%p", static_cast<void*>(this));
    4413             :     auto string =
    4414             :         v8::String::NewFromUtf8(isolate, buffer.start(),
    4415         215 :                                 v8::NewStringType::kNormal).ToLocalChecked();
    4416             :     cell_.Reset(isolate, string);
    4417         430 :     (*instance_counter_)++;
    4418         215 :   }
    4419             : 
    4420         215 :   ~TwoPassCallbackData() {
    4421         215 :     CHECK(first_pass_called_);
    4422         215 :     CHECK(second_pass_called_);
    4423         215 :     CHECK(cell_.IsEmpty());
    4424         215 :     (*instance_counter_)--;
    4425         215 :   }
    4426             : 
    4427         215 :   void FirstPass() {
    4428         215 :     CHECK(!first_pass_called_);
    4429         215 :     CHECK(!second_pass_called_);
    4430         215 :     CHECK(!cell_.IsEmpty());
    4431             :     cell_.Reset();
    4432         215 :     first_pass_called_ = true;
    4433         215 :   }
    4434             : 
    4435         215 :   void SecondPass() {
    4436         215 :     CHECK(first_pass_called_);
    4437         215 :     CHECK(!second_pass_called_);
    4438         215 :     CHECK(cell_.IsEmpty());
    4439         215 :     second_pass_called_ = true;
    4440         215 :     delete this;
    4441         215 :   }
    4442             : 
    4443             :   void SetWeak() {
    4444             :     cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
    4445             :   }
    4446             : 
    4447          15 :   void MarkTriggerGc() { trigger_gc_ = true; }
    4448             :   bool trigger_gc() { return trigger_gc_; }
    4449             : 
    4450             :   int* instance_counter() { return instance_counter_; }
    4451             : 
    4452             :  private:
    4453             :   bool first_pass_called_;
    4454             :   bool second_pass_called_;
    4455             :   bool trigger_gc_;
    4456             :   v8::Global<v8::String> cell_;
    4457             :   int* instance_counter_;
    4458             : };
    4459             : 
    4460             : 
    4461         445 : void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4462         215 :   ApiTestFuzzer::Fuzz();
    4463         215 :   bool trigger_gc = data.GetParameter()->trigger_gc();
    4464         215 :   int* instance_counter = data.GetParameter()->instance_counter();
    4465         215 :   data.GetParameter()->SecondPass();
    4466         430 :   if (!trigger_gc) return;
    4467          15 :   auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
    4468             :   data_2->SetWeak();
    4469          15 :   CcTest::CollectAllGarbage();
    4470             : }
    4471             : 
    4472             : 
    4473         430 : void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
    4474         215 :   data.GetParameter()->FirstPass();
    4475             :   data.SetSecondPassCallback(SecondPassCallback);
    4476         215 : }
    4477             : 
    4478             : }  // namespace
    4479             : 
    4480             : 
    4481       25880 : TEST(TwoPassPhantomCallbacks) {
    4482           5 :   auto isolate = CcTest::isolate();
    4483             :   const size_t kLength = 20;
    4484           5 :   int instance_counter = 0;
    4485         105 :   for (size_t i = 0; i < kLength; ++i) {
    4486         100 :     auto data = new TwoPassCallbackData(isolate, &instance_counter);
    4487             :     data->SetWeak();
    4488             :   }
    4489           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4490           5 :   CcTest::CollectAllGarbage();
    4491           5 :   EmptyMessageQueues(isolate);
    4492           5 :   CHECK_EQ(0, instance_counter);
    4493           5 : }
    4494             : 
    4495             : 
    4496       25880 : TEST(TwoPassPhantomCallbacksNestedGc) {
    4497           5 :   auto isolate = CcTest::isolate();
    4498             :   const size_t kLength = 20;
    4499             :   TwoPassCallbackData* array[kLength];
    4500           5 :   int instance_counter = 0;
    4501         105 :   for (size_t i = 0; i < kLength; ++i) {
    4502         100 :     array[i] = new TwoPassCallbackData(isolate, &instance_counter);
    4503             :     array[i]->SetWeak();
    4504             :   }
    4505           5 :   array[5]->MarkTriggerGc();
    4506           5 :   array[10]->MarkTriggerGc();
    4507           5 :   array[15]->MarkTriggerGc();
    4508           5 :   CHECK_EQ(static_cast<int>(kLength), instance_counter);
    4509           5 :   CcTest::CollectAllGarbage();
    4510           5 :   EmptyMessageQueues(isolate);
    4511           5 :   CHECK_EQ(0, instance_counter);
    4512           5 : }
    4513             : 
    4514             : 
    4515             : namespace {
    4516             : 
    4517          30 : void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
    4518             : 
    4519             : 
    4520          20 : Local<v8::Object> NewObjectForIntKey(
    4521             :     v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
    4522             :     int key) {
    4523             :   auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
    4524          20 :   auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
    4525          20 :   obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
    4526          20 :   return obj;
    4527             : }
    4528             : 
    4529             : 
    4530             : template <typename K, typename V>
    4531             : class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
    4532             :  public:
    4533             :   typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
    4534             :   static const v8::PersistentContainerCallbackType kCallbackType =
    4535             :       v8::kWeakWithInternalFields;
    4536             :   struct WeakCallbackDataType {
    4537             :     MapType* map;
    4538             :     K key;
    4539             :   };
    4540             :   static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
    4541             :                                                      Local<V> value) {
    4542          25 :     WeakCallbackDataType* data = new WeakCallbackDataType;
    4543          25 :     data->map = map;
    4544          25 :     data->key = key;
    4545             :     return data;
    4546             :   }
    4547             :   static MapType* MapFromWeakCallbackInfo(
    4548           5 :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4549           5 :     return data.GetParameter()->map;
    4550             :   }
    4551             :   static K KeyFromWeakCallbackInfo(
    4552           5 :       const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
    4553          10 :     return data.GetParameter()->key;
    4554             :   }
    4555          25 :   static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
    4556           5 :   static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
    4557           5 :     CHECK_EQ(IntKeyToVoidPointer(key),
    4558             :              v8::Object::GetAlignedPointerFromInternalField(value, 0));
    4559           5 :   }
    4560             :   static void OnWeakCallback(
    4561             :       const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
    4562           5 :   static void DisposeWeak(
    4563             :       const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
    4564             :     K key = KeyFromWeakCallbackInfo(info);
    4565           5 :     CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
    4566             :     DisposeCallbackData(info.GetParameter());
    4567           5 :   }
    4568             : };
    4569             : 
    4570             : 
    4571             : template <typename Map>
    4572          10 : void TestGlobalValueMap() {
    4573          10 :   LocalContext env;
    4574          20 :   v8::Isolate* isolate = env->GetIsolate();
    4575             :   v8::Global<ObjectTemplate> templ;
    4576             :   {
    4577          10 :     HandleScope scope(isolate);
    4578          10 :     auto t = ObjectTemplate::New(isolate);
    4579          10 :     t->SetInternalFieldCount(1);
    4580          10 :     templ.Reset(isolate, t);
    4581             :   }
    4582             :   Map map(isolate);
    4583          40 :   v8::internal::GlobalHandles* global_handles =
    4584             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4585             :   size_t initial_handle_count = global_handles->handles_count();
    4586          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4587             :   {
    4588          10 :     HandleScope scope(isolate);
    4589          10 :     Local<v8::Object> obj = map.Get(7);
    4590          10 :     CHECK(obj.IsEmpty());
    4591          10 :     Local<v8::Object> expected = v8::Object::New(isolate);
    4592          20 :     map.Set(7, expected);
    4593          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4594          10 :     obj = map.Get(7);
    4595          20 :     CHECK(expected->Equals(env.local(), obj).FromJust());
    4596             :     {
    4597          10 :       typename Map::PersistentValueReference ref = map.GetReference(7);
    4598          20 :       CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4599             :     }
    4600          10 :     v8::Global<v8::Object> removed = map.Remove(7);
    4601          10 :     CHECK_EQ(0, static_cast<int>(map.Size()));
    4602          10 :     CHECK(expected == removed);
    4603          20 :     removed = map.Remove(7);
    4604          10 :     CHECK(removed.IsEmpty());
    4605          20 :     map.Set(8, expected);
    4606          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4607          20 :     map.Set(8, expected);
    4608          10 :     CHECK_EQ(1, static_cast<int>(map.Size()));
    4609             :     {
    4610             :       typename Map::PersistentValueReference ref;
    4611          10 :       Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
    4612          30 :       removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
    4613          10 :       CHECK_EQ(1, static_cast<int>(map.Size()));
    4614          10 :       CHECK(expected == removed);
    4615          20 :       CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
    4616          10 :     }
    4617             :   }
    4618          10 :   CHECK_EQ(initial_handle_count + 1, global_handles->handles_count());
    4619             :   if (map.IsWeak()) {
    4620           5 :     CcTest::PreciseCollectAllGarbage();
    4621             :   } else {
    4622           5 :     map.Clear();
    4623             :   }
    4624          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4625          10 :   CHECK_EQ(initial_handle_count, global_handles->handles_count());
    4626             :   {
    4627          10 :     HandleScope scope(isolate);
    4628          10 :     Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
    4629          20 :     map.Set(9, value);
    4630          10 :     map.Clear();
    4631             :   }
    4632          10 :   CHECK_EQ(0, static_cast<int>(map.Size()));
    4633          20 :   CHECK_EQ(initial_handle_count, global_handles->handles_count());
    4634          10 : }
    4635             : 
    4636             : }  // namespace
    4637             : 
    4638             : 
    4639       25880 : TEST(GlobalValueMap) {
    4640             :   // Default case, w/o weak callbacks:
    4641           5 :   TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
    4642             : 
    4643             :   // Custom traits with weak callbacks:
    4644             :   typedef v8::GlobalValueMap<int, v8::Object,
    4645             :                              PhantomStdMapTraits<int, v8::Object>> WeakMap;
    4646           5 :   TestGlobalValueMap<WeakMap>();
    4647           5 : }
    4648             : 
    4649             : 
    4650       25880 : TEST(PersistentValueVector) {
    4651           5 :   LocalContext env;
    4652           5 :   v8::Isolate* isolate = env->GetIsolate();
    4653          15 :   v8::internal::GlobalHandles* global_handles =
    4654             :       reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
    4655             :   size_t handle_count = global_handles->handles_count();
    4656          10 :   HandleScope scope(isolate);
    4657             : 
    4658           5 :   v8::PersistentValueVector<v8::Object> vector(isolate);
    4659             : 
    4660           5 :   Local<v8::Object> obj1 = v8::Object::New(isolate);
    4661           5 :   Local<v8::Object> obj2 = v8::Object::New(isolate);
    4662           5 :   v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
    4663             : 
    4664           5 :   CHECK(vector.IsEmpty());
    4665           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4666             : 
    4667             :   vector.ReserveCapacity(3);
    4668           5 :   CHECK(vector.IsEmpty());
    4669             : 
    4670           5 :   vector.Append(obj1);
    4671           5 :   vector.Append(obj2);
    4672           5 :   vector.Append(obj1);
    4673           5 :   vector.Append(obj3.Pass());
    4674           5 :   vector.Append(obj1);
    4675             : 
    4676           5 :   CHECK(!vector.IsEmpty());
    4677           5 :   CHECK_EQ(5, static_cast<int>(vector.Size()));
    4678           5 :   CHECK(obj3.IsEmpty());
    4679          15 :   CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
    4680          15 :   CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
    4681          15 :   CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
    4682          20 :   CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
    4683             : 
    4684           5 :   CHECK_EQ(5 + handle_count, global_handles->handles_count());
    4685             : 
    4686           5 :   vector.Clear();
    4687           5 :   CHECK(vector.IsEmpty());
    4688           5 :   CHECK_EQ(0, static_cast<int>(vector.Size()));
    4689          10 :   CHECK_EQ(handle_count, global_handles->handles_count());
    4690           5 : }
    4691             : 
    4692             : 
    4693       25881 : THREADED_TEST(GlobalHandleUpcast) {
    4694           6 :   v8::Isolate* isolate = CcTest::isolate();
    4695           6 :   v8::HandleScope scope(isolate);
    4696           6 :   v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
    4697             :   v8::Persistent<String> global_string(isolate, local);
    4698             :   v8::Persistent<Value>& global_value =
    4699             :       v8::Persistent<Value>::Cast(global_string);
    4700           6 :   CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
    4701           6 :   CHECK(global_string == v8::Persistent<String>::Cast(global_value));
    4702           6 :   global_string.Reset();
    4703           6 : }
    4704             : 
    4705             : 
    4706       25881 : THREADED_TEST(HandleEquality) {
    4707           6 :   v8::Isolate* isolate = CcTest::isolate();
    4708             :   v8::Persistent<String> global1;
    4709             :   v8::Persistent<String> global2;
    4710             :   {
    4711           6 :     v8::HandleScope scope(isolate);
    4712          12 :     global1.Reset(isolate, v8_str("str"));
    4713          12 :     global2.Reset(isolate, v8_str("str2"));
    4714             :   }
    4715           6 :   CHECK(global1 == global1);
    4716           6 :   CHECK(!(global1 != global1));
    4717             :   {
    4718           6 :     v8::HandleScope scope(isolate);
    4719             :     Local<String> local1 = Local<String>::New(isolate, global1);
    4720             :     Local<String> local2 = Local<String>::New(isolate, global2);
    4721             : 
    4722           6 :     CHECK(global1 == local1);
    4723           6 :     CHECK(!(global1 != local1));
    4724           6 :     CHECK(local1 == global1);
    4725           6 :     CHECK(!(local1 != global1));
    4726             : 
    4727           6 :     CHECK(!(global1 == local2));
    4728           6 :     CHECK(global1 != local2);
    4729           6 :     CHECK(!(local2 == global1));
    4730           6 :     CHECK(local2 != global1);
    4731             : 
    4732           6 :     CHECK(!(local1 == local2));
    4733           6 :     CHECK(local1 != local2);
    4734             : 
    4735             :     Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
    4736           6 :     CHECK(local1 == anotherLocal1);
    4737           6 :     CHECK(!(local1 != anotherLocal1));
    4738             :   }
    4739             :   global1.Reset();
    4740             :   global2.Reset();
    4741           6 : }
    4742             : 
    4743             : 
    4744       25881 : THREADED_TEST(LocalHandle) {
    4745           6 :   v8::HandleScope scope(CcTest::isolate());
    4746             :   v8::Local<String> local =
    4747           6 :       v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
    4748           6 :   CHECK_EQ(3, local->Length());
    4749           6 : }
    4750             : 
    4751             : 
    4752             : class WeakCallCounter {
    4753             :  public:
    4754           5 :   explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
    4755             :   int id() { return id_; }
    4756          10 :   void increment() { number_of_weak_calls_++; }
    4757             :   int NumberOfWeakCalls() { return number_of_weak_calls_; }
    4758             : 
    4759             :  private:
    4760             :   int id_;
    4761             :   int number_of_weak_calls_;
    4762             : };
    4763             : 
    4764             : 
    4765             : template <typename T>
    4766             : struct WeakCallCounterAndPersistent {
    4767             :   explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
    4768          10 :       : counter(counter) {}
    4769             :   WeakCallCounter* counter;
    4770             :   v8::Persistent<T> handle;
    4771             : };
    4772             : 
    4773             : 
    4774             : template <typename T>
    4775          10 : static void WeakPointerCallback(
    4776          20 :     const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
    4777          10 :   CHECK_EQ(1234, data.GetParameter()->counter->id());
    4778             :   data.GetParameter()->counter->increment();
    4779             :   data.GetParameter()->handle.Reset();
    4780          10 : }
    4781             : 
    4782       25881 : THREADED_TEST(ScriptException) {
    4783           6 :   LocalContext env;
    4784          12 :   v8::HandleScope scope(env->GetIsolate());
    4785             :   Local<Script> script = v8_compile("throw 'panama!';");
    4786          12 :   v8::TryCatch try_catch(env->GetIsolate());
    4787           6 :   v8::MaybeLocal<Value> result = script->Run(env.local());
    4788           6 :   CHECK(result.IsEmpty());
    4789           6 :   CHECK(try_catch.HasCaught());
    4790          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    4791          12 :   CHECK_EQ(0, strcmp(*exception_value, "panama!"));
    4792           6 : }
    4793             : 
    4794             : 
    4795       25880 : TEST(TryCatchCustomException) {
    4796           5 :   LocalContext env;
    4797           5 :   v8::Isolate* isolate = env->GetIsolate();
    4798          10 :   v8::HandleScope scope(isolate);
    4799          10 :   v8::TryCatch try_catch(isolate);
    4800             :   CompileRun(
    4801             :       "function CustomError() { this.a = 'b'; }"
    4802             :       "(function f() { throw new CustomError(); })();");
    4803           5 :   CHECK(try_catch.HasCaught());
    4804          35 :   CHECK(try_catch.Exception()
    4805             :             ->ToObject(env.local())
    4806             :             .ToLocalChecked()
    4807             :             ->Get(env.local(), v8_str("a"))
    4808             :             .ToLocalChecked()
    4809             :             ->Equals(env.local(), v8_str("b"))
    4810           5 :             .FromJust());
    4811           5 : }
    4812             : 
    4813             : 
    4814             : bool message_received;
    4815             : 
    4816             : 
    4817           6 : static void check_message_0(v8::Local<v8::Message> message,
    4818             :                             v8::Local<Value> data) {
    4819          18 :   CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
    4820             :                      .FromJust());
    4821          12 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4822             :                      .ResourceName()
    4823             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4824             :                      .FromJust());
    4825           6 :   CHECK(!message->IsSharedCrossOrigin());
    4826           6 :   message_received = true;
    4827           6 : }
    4828             : 
    4829             : 
    4830       25881 : THREADED_TEST(MessageHandler0) {
    4831           6 :   message_received = false;
    4832           6 :   v8::HandleScope scope(CcTest::isolate());
    4833           6 :   CHECK(!message_received);
    4834          12 :   LocalContext context;
    4835           6 :   CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
    4836           6 :   v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
    4837          18 :   CHECK(script->Run(context.local()).IsEmpty());
    4838           6 :   CHECK(message_received);
    4839             :   // clear out the message listener
    4840          12 :   CcTest::isolate()->RemoveMessageListeners(check_message_0);
    4841           6 : }
    4842             : 
    4843             : 
    4844           5 : static void check_message_1(v8::Local<v8::Message> message,
    4845             :                             v8::Local<Value> data) {
    4846           5 :   CHECK(data->IsNumber());
    4847          10 :   CHECK_EQ(1337,
    4848             :            data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
    4849           5 :   CHECK(!message->IsSharedCrossOrigin());
    4850           5 :   message_received = true;
    4851           5 : }
    4852             : 
    4853             : 
    4854       25880 : TEST(MessageHandler1) {
    4855           5 :   message_received = false;
    4856           5 :   v8::HandleScope scope(CcTest::isolate());
    4857           5 :   CHECK(!message_received);
    4858           5 :   CcTest::isolate()->AddMessageListener(check_message_1);
    4859          10 :   LocalContext context;
    4860             :   CompileRun("throw 1337;");
    4861           5 :   CHECK(message_received);
    4862             :   // clear out the message listener
    4863          10 :   CcTest::isolate()->RemoveMessageListeners(check_message_1);
    4864           5 : }
    4865             : 
    4866             : 
    4867           5 : static void check_message_2(v8::Local<v8::Message> message,
    4868             :                             v8::Local<Value> data) {
    4869           5 :   LocalContext context;
    4870           5 :   CHECK(data->IsObject());
    4871             :   v8::Local<v8::Value> hidden_property =
    4872             :       v8::Object::Cast(*data)
    4873             :           ->GetPrivate(
    4874             :               context.local(),
    4875           5 :               v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
    4876          10 :           .ToLocalChecked();
    4877          15 :   CHECK(v8_str("hidden value")
    4878             :             ->Equals(context.local(), hidden_property)
    4879             :             .FromJust());
    4880           5 :   CHECK(!message->IsSharedCrossOrigin());
    4881           5 :   message_received = true;
    4882           5 : }
    4883             : 
    4884             : 
    4885       25880 : TEST(MessageHandler2) {
    4886           5 :   message_received = false;
    4887           5 :   v8::HandleScope scope(CcTest::isolate());
    4888           5 :   CHECK(!message_received);
    4889           5 :   CcTest::isolate()->AddMessageListener(check_message_2);
    4890          10 :   LocalContext context;
    4891           5 :   v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
    4892             :   v8::Object::Cast(*error)
    4893             :       ->SetPrivate(context.local(),
    4894             :                    v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
    4895          15 :                    v8_str("hidden value"))
    4896          10 :       .FromJust();
    4897          25 :   CHECK(context->Global()
    4898             :             ->Set(context.local(), v8_str("error"), error)
    4899             :             .FromJust());
    4900             :   CompileRun("throw error;");
    4901           5 :   CHECK(message_received);
    4902             :   // clear out the message listener
    4903          10 :   CcTest::isolate()->RemoveMessageListeners(check_message_2);
    4904           5 : }
    4905             : 
    4906             : 
    4907           5 : static void check_message_3(v8::Local<v8::Message> message,
    4908             :                             v8::Local<Value> data) {
    4909           5 :   CHECK(message->IsSharedCrossOrigin());
    4910          10 :   CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
    4911          10 :   CHECK(message->GetScriptOrigin().Options().IsOpaque());
    4912          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4913             :                      .ResourceName()
    4914             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4915             :                      .FromJust());
    4916          10 :   CHECK_EQ(7.40, message->GetScriptOrigin()
    4917             :                      .SourceMapUrl()
    4918             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4919             :                      .FromJust());
    4920           5 :   message_received = true;
    4921           5 : }
    4922             : 
    4923             : 
    4924       25880 : TEST(MessageHandler3) {
    4925           5 :   message_received = false;
    4926           5 :   v8::Isolate* isolate = CcTest::isolate();
    4927           5 :   v8::HandleScope scope(isolate);
    4928           5 :   CHECK(!message_received);
    4929           5 :   isolate->AddMessageListener(check_message_3);
    4930          10 :   LocalContext context;
    4931             :   v8::ScriptOrigin origin =
    4932             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4933             :                        v8::Integer::New(isolate, 2), v8::True(isolate),
    4934           5 :                        Local<v8::Integer>(), v8_str("7.40"), v8::True(isolate));
    4935             :   v8::Local<v8::Script> script =
    4936           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4937           5 :           .ToLocalChecked();
    4938          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4939           5 :   CHECK(message_received);
    4940             :   // clear out the message listener
    4941          10 :   isolate->RemoveMessageListeners(check_message_3);
    4942           5 : }
    4943             : 
    4944             : 
    4945           5 : static void check_message_4(v8::Local<v8::Message> message,
    4946             :                             v8::Local<Value> data) {
    4947           5 :   CHECK(!message->IsSharedCrossOrigin());
    4948          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4949             :                      .ResourceName()
    4950             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4951             :                      .FromJust());
    4952           5 :   message_received = true;
    4953           5 : }
    4954             : 
    4955             : 
    4956       25880 : TEST(MessageHandler4) {
    4957           5 :   message_received = false;
    4958           5 :   v8::Isolate* isolate = CcTest::isolate();
    4959           5 :   v8::HandleScope scope(isolate);
    4960           5 :   CHECK(!message_received);
    4961           5 :   isolate->AddMessageListener(check_message_4);
    4962          10 :   LocalContext context;
    4963             :   v8::ScriptOrigin origin =
    4964             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    4965           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    4966             :   v8::Local<v8::Script> script =
    4967           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
    4968           5 :           .ToLocalChecked();
    4969          10 :   CHECK(script->Run(context.local()).IsEmpty());
    4970           5 :   CHECK(message_received);
    4971             :   // clear out the message listener
    4972          10 :   isolate->RemoveMessageListeners(check_message_4);
    4973           5 : }
    4974             : 
    4975             : 
    4976           5 : static void check_message_5a(v8::Local<v8::Message> message,
    4977             :                              v8::Local<Value> data) {
    4978           5 :   CHECK(message->IsSharedCrossOrigin());
    4979          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4980             :                      .ResourceName()
    4981             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4982             :                      .FromJust());
    4983           5 :   message_received = true;
    4984           5 : }
    4985             : 
    4986             : 
    4987           5 : static void check_message_5b(v8::Local<v8::Message> message,
    4988             :                              v8::Local<Value> data) {
    4989           5 :   CHECK(!message->IsSharedCrossOrigin());
    4990          10 :   CHECK_EQ(6.75, message->GetScriptOrigin()
    4991             :                      .ResourceName()
    4992             :                      ->NumberValue(CcTest::isolate()->GetCurrentContext())
    4993             :                      .FromJust());
    4994           5 :   message_received = true;
    4995           5 : }
    4996             : 
    4997             : 
    4998       25880 : TEST(MessageHandler5) {
    4999           5 :   message_received = false;
    5000           5 :   v8::Isolate* isolate = CcTest::isolate();
    5001           5 :   v8::HandleScope scope(isolate);
    5002           5 :   CHECK(!message_received);
    5003           5 :   isolate->AddMessageListener(check_message_5a);
    5004          10 :   LocalContext context;
    5005             :   v8::ScriptOrigin origin1 =
    5006             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    5007           5 :                        v8::Integer::New(isolate, 2), v8::True(isolate));
    5008             :   v8::Local<v8::Script> script =
    5009           5 :       Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
    5010           5 :           .ToLocalChecked();
    5011          10 :   CHECK(script->Run(context.local()).IsEmpty());
    5012           5 :   CHECK(message_received);
    5013             :   // clear out the message listener
    5014           5 :   isolate->RemoveMessageListeners(check_message_5a);
    5015             : 
    5016           5 :   message_received = false;
    5017           5 :   isolate->AddMessageListener(check_message_5b);
    5018             :   v8::ScriptOrigin origin2 =
    5019             :       v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
    5020           5 :                        v8::Integer::New(isolate, 2), v8::False(isolate));
    5021           5 :   script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
    5022           5 :                .ToLocalChecked();
    5023          10 :   CHECK(script->Run(context.local()).IsEmpty());
    5024           5 :   CHECK(message_received);
    5025             :   // clear out the message listener
    5026          10 :   isolate->RemoveMessageListeners(check_message_5b);
    5027           5 : }
    5028             : 
    5029             : 
    5030       25881 : THREADED_TEST(GetSetProperty) {
    5031           6 :   LocalContext context;
    5032           6 :   v8::Isolate* isolate = context->GetIsolate();
    5033          12 :   v8::HandleScope scope(isolate);
    5034          30 :   CHECK(context->Global()
    5035             :             ->Set(context.local(), v8_str("foo"), v8_num(14))
    5036             :             .FromJust());
    5037          30 :   CHECK(context->Global()
    5038             :             ->Set(context.local(), v8_str("12"), v8_num(92))
    5039             :             .FromJust());
    5040          30 :   CHECK(context->Global()
    5041             :             ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
    5042             :             .FromJust());
    5043          24 :   CHECK(context->Global()
    5044             :             ->Set(context.local(), v8_num(13), v8_num(56))
    5045             :             .FromJust());
    5046             :   Local<Value> foo = CompileRun("this.foo");
    5047          12 :   CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
    5048             :   Local<Value> twelve = CompileRun("this[12]");
    5049          12 :   CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
    5050             :   Local<Value> sixteen = CompileRun("this[16]");
    5051          12 :   CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
    5052             :   Local<Value> thirteen = CompileRun("this[13]");
    5053          12 :   CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
    5054          36 :   CHECK_EQ(92, context->Global()
    5055             :                    ->Get(context.local(), v8::Integer::New(isolate, 12))
    5056             :                    .ToLocalChecked()
    5057             :                    ->Int32Value(context.local())
    5058             :                    .FromJust());
    5059          36 :   CHECK_EQ(92, context->Global()
    5060             :                    ->Get(context.local(), v8_str("12"))
    5061             :                    .ToLocalChecked()
    5062             :                    ->Int32Value(context.local())
    5063             :                    .FromJust());
    5064          30 :   CHECK_EQ(92, context->Global()
    5065             :                    ->Get(context.local(), v8_num(12))
    5066             :                    .ToLocalChecked()
    5067             :                    ->Int32Value(context.local())
    5068             :                    .FromJust());
    5069          36 :   CHECK_EQ(32, context->Global()
    5070             :                    ->Get(context.local(), v8::Integer::New(isolate, 16))
    5071             :                    .ToLocalChecked()
    5072             :                    ->Int32Value(context.local())
    5073             :                    .FromJust());
    5074          36 :   CHECK_EQ(32, context->Global()
    5075             :                    ->Get(context.local(), v8_str("16"))
    5076             :                    .ToLocalChecked()
    5077             :                    ->Int32Value(context.local())
    5078             :                    .FromJust());
    5079          30 :   CHECK_EQ(32, context->Global()
    5080             :                    ->Get(context.local(), v8_num(16))
    5081             :                    .ToLocalChecked()
    5082             :                    ->Int32Value(context.local())
    5083             :                    .FromJust());
    5084          36 :   CHECK_EQ(56, context->Global()
    5085             :                    ->Get(context.local(), v8::Integer::New(isolate, 13))
    5086             :                    .ToLocalChecked()
    5087             :                    ->Int32Value(context.local())
    5088             :                    .FromJust());
    5089          36 :   CHECK_EQ(56, context->Global()
    5090             :                    ->Get(context.local(), v8_str("13"))
    5091             :                    .ToLocalChecked()
    5092             :                    ->Int32Value(context.local())
    5093             :                    .FromJust());
    5094          30 :   CHECK_EQ(56, context->Global()
    5095             :                    ->Get(context.local(), v8_num(13))
    5096             :                    .ToLocalChecked()
    5097             :                    ->Int32Value(context.local())
    5098           6 :                    .FromJust());
    5099           6 : }
    5100             : 
    5101             : 
    5102       25881 : THREADED_TEST(PropertyAttributes) {
    5103           6 :   LocalContext context;
    5104          12 :   v8::HandleScope scope(context->GetIsolate());
    5105             :   // none
    5106           6 :   Local<String> prop = v8_str("none");
    5107          30 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
    5108          24 :   CHECK_EQ(v8::None, context->Global()
    5109             :                          ->GetPropertyAttributes(context.local(), prop)
    5110             :                          .FromJust());
    5111             :   // read-only
    5112           6 :   prop = v8_str("read_only");
    5113             :   context->Global()
    5114          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
    5115          12 :       .FromJust();
    5116          36 :   CHECK_EQ(7, context->Global()
    5117             :                   ->Get(context.local(), prop)
    5118             :                   .ToLocalChecked()
    5119             :                   ->Int32Value(context.local())
    5120             :                   .FromJust());
    5121          24 :   CHECK_EQ(v8::ReadOnly, context->Global()
    5122             :                              ->GetPropertyAttributes(context.local(), prop)
    5123             :                              .FromJust());
    5124             :   CompileRun("read_only = 9");
    5125          36 :   CHECK_EQ(7, context->Global()
    5126             :                   ->Get(context.local(), prop)
    5127             :                   .ToLocalChecked()
    5128             :                   ->Int32Value(context.local())
    5129             :                   .FromJust());
    5130          30 :   CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
    5131          36 :   CHECK_EQ(7, context->Global()
    5132             :                   ->Get(context.local(), prop)
    5133             :                   .ToLocalChecked()
    5134             :                   ->Int32Value(context.local())
    5135             :                   .FromJust());
    5136             :   // dont-delete
    5137           6 :   prop = v8_str("dont_delete");
    5138             :   context->Global()
    5139          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
    5140          12 :       .FromJust();
    5141          36 :   CHECK_EQ(13, context->Global()
    5142             :                    ->Get(context.local(), prop)
    5143             :                    .ToLocalChecked()
    5144             :                    ->Int32Value(context.local())
    5145             :                    .FromJust());
    5146             :   CompileRun("delete dont_delete");
    5147          36 :   CHECK_EQ(13, context->Global()
    5148             :                    ->Get(context.local(), prop)
    5149             :                    .ToLocalChecked()
    5150             :                    ->Int32Value(context.local())
    5151             :                    .FromJust());
    5152          24 :   CHECK_EQ(v8::DontDelete, context->Global()
    5153             :                                ->GetPropertyAttributes(context.local(), prop)
    5154             :                                .FromJust());
    5155             :   // dont-enum
    5156           6 :   prop = v8_str("dont_enum");
    5157             :   context->Global()
    5158          24 :       ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
    5159          12 :       .FromJust();
    5160          24 :   CHECK_EQ(v8::DontEnum, context->Global()
    5161             :                              ->GetPropertyAttributes(context.local(), prop)
    5162             :                              .FromJust());
    5163             :   // absent
    5164           6 :   prop = v8_str("absent");
    5165          24 :   CHECK_EQ(v8::None, context->Global()
    5166             :                          ->GetPropertyAttributes(context.local(), prop)
    5167             :                          .FromJust());
    5168           6 :   Local<Value> fake_prop = v8_num(1);
    5169          24 :   CHECK_EQ(v8::None, context->Global()
    5170             :                          ->GetPropertyAttributes(context.local(), fake_prop)
    5171             :                          .FromJust());
    5172             :   // exception
    5173          12 :   TryCatch try_catch(context->GetIsolate());
    5174             :   Local<Value> exception =
    5175           6 :       CompileRun("({ toString: function() { throw 'exception';} })");
    5176          24 :   CHECK(context->Global()
    5177             :             ->GetPropertyAttributes(context.local(), exception)
    5178             :             .IsNothing());
    5179           6 :   CHECK(try_catch.HasCaught());
    5180             :   String::Utf8Value exception_value(context->GetIsolate(),
    5181          18 :                                     try_catch.Exception());
    5182           6 :   CHECK_EQ(0, strcmp("exception", *exception_value));
    5183          12 :   try_catch.Reset();
    5184           6 : }
    5185             : 
    5186             : 
    5187       25881 : THREADED_TEST(Array) {
    5188           6 :   LocalContext context;
    5189          12 :   v8::HandleScope scope(context->GetIsolate());
    5190           6 :   Local<v8::Array> array = v8::Array::New(context->GetIsolate());
    5191           6 :   CHECK_EQ(0u, array->Length());
    5192          12 :   CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
    5193          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5194          12 :   CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
    5195          12 :   CHECK(!array->Has(context.local(), 100).FromJust());
    5196          12 :   CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
    5197           6 :   CHECK_EQ(3u, array->Length());
    5198          12 :   CHECK(!array->Has(context.local(), 0).FromJust());
    5199          12 :   CHECK(!array->Has(context.local(), 1).FromJust());
    5200          12 :   CHECK(array->Has(context.local(), 2).FromJust());
    5201          18 :   CHECK_EQ(7, array->Get(context.local(), 2)
    5202             :                   .ToLocalChecked()
    5203             :                   ->Int32Value(context.local())
    5204             :                   .FromJust());
    5205             :   Local<Value> obj = CompileRun("[1, 2, 3]");
    5206             :   Local<v8::Array> arr = obj.As<v8::Array>();
    5207           6 :   CHECK_EQ(3u, arr->Length());
    5208          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5209             :                   .ToLocalChecked()
    5210             :                   ->Int32Value(context.local())
    5211             :                   .FromJust());
    5212          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5213             :                   .ToLocalChecked()
    5214             :                   ->Int32Value(context.local())
    5215             :                   .FromJust());
    5216          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5217             :                   .ToLocalChecked()
    5218             :                   ->Int32Value(context.local())
    5219             :                   .FromJust());
    5220           6 :   array = v8::Array::New(context->GetIsolate(), 27);
    5221           6 :   CHECK_EQ(27u, array->Length());
    5222           6 :   array = v8::Array::New(context->GetIsolate(), -27);
    5223           6 :   CHECK_EQ(0u, array->Length());
    5224             : 
    5225          12 :   std::vector<Local<Value>> vector = {v8_num(1), v8_num(2), v8_num(3)};
    5226          12 :   array = v8::Array::New(context->GetIsolate(), vector.data(), vector.size());
    5227          12 :   CHECK_EQ(vector.size(), array->Length());
    5228          18 :   CHECK_EQ(1, arr->Get(context.local(), 0)
    5229             :                   .ToLocalChecked()
    5230             :                   ->Int32Value(context.local())
    5231             :                   .FromJust());
    5232          18 :   CHECK_EQ(2, arr->Get(context.local(), 1)
    5233             :                   .ToLocalChecked()
    5234             :                   ->Int32Value(context.local())
    5235             :                   .FromJust());
    5236          18 :   CHECK_EQ(3, arr->Get(context.local(), 2)
    5237             :                   .ToLocalChecked()
    5238             :                   ->Int32Value(context.local())
    5239           6 :                   .FromJust());
    5240           6 : }
    5241             : 
    5242             : 
    5243         180 : void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5244          30 :   v8::EscapableHandleScope scope(args.GetIsolate());
    5245          30 :   ApiTestFuzzer::Fuzz();
    5246          30 :   Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
    5247         180 :   for (int i = 0; i < args.Length(); i++) {
    5248         180 :     CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
    5249             :               .FromJust());
    5250             :   }
    5251             :   args.GetReturnValue().Set(scope.Escape(result));
    5252          30 : }
    5253             : 
    5254             : 
    5255       25881 : THREADED_TEST(Vector) {
    5256           6 :   v8::Isolate* isolate = CcTest::isolate();
    5257           6 :   v8::HandleScope scope(isolate);
    5258           6 :   Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
    5259          18 :   global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
    5260          12 :   LocalContext context(nullptr, global);
    5261             : 
    5262             :   const char* fun = "f()";
    5263             :   Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
    5264           6 :   CHECK_EQ(0u, a0->Length());
    5265             : 
    5266             :   const char* fun2 = "f(11)";
    5267             :   Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
    5268           6 :   CHECK_EQ(1u, a1->Length());
    5269          18 :   CHECK_EQ(11, a1->Get(context.local(), 0)
    5270             :                    .ToLocalChecked()
    5271             :                    ->Int32Value(context.local())
    5272             :                    .FromJust());
    5273             : 
    5274             :   const char* fun3 = "f(12, 13)";
    5275             :   Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
    5276           6 :   CHECK_EQ(2u, a2->Length());
    5277          18 :   CHECK_EQ(12, a2->Get(context.local(), 0)
    5278             :                    .ToLocalChecked()
    5279             :                    ->Int32Value(context.local())
    5280             :                    .FromJust());
    5281          18 :   CHECK_EQ(13, a2->Get(context.local(), 1)
    5282             :                    .ToLocalChecked()
    5283             :                    ->Int32Value(context.local())
    5284             :                    .FromJust());
    5285             : 
    5286             :   const char* fun4 = "f(14, 15, 16)";
    5287             :   Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
    5288           6 :   CHECK_EQ(3u, a3->Length());
    5289          18 :   CHECK_EQ(14, a3->Get(context.local(), 0)
    5290             :                    .ToLocalChecked()
    5291             :                    ->Int32Value(context.local())
    5292             :                    .FromJust());
    5293          18 :   CHECK_EQ(15, a3->Get(context.local(), 1)
    5294             :                    .ToLocalChecked()
    5295             :                    ->Int32Value(context.local())
    5296             :                    .FromJust());
    5297          18 :   CHECK_EQ(16, a3->Get(context.local(), 2)
    5298             :                    .ToLocalChecked()
    5299             :                    ->Int32Value(context.local())
    5300             :                    .FromJust());
    5301             : 
    5302             :   const char* fun5 = "f(17, 18, 19, 20)";
    5303             :   Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
    5304           6 :   CHECK_EQ(4u, a4->Length());
    5305          18 :   CHECK_EQ(17, a4->Get(context.local(), 0)
    5306             :                    .ToLocalChecked()
    5307             :                    ->Int32Value(context.local())
    5308             :                    .FromJust());
    5309          18 :   CHECK_EQ(18, a4->Get(context.local(), 1)
    5310             :                    .ToLocalChecked()
    5311             :                    ->Int32Value(context.local())
    5312             :                    .FromJust());
    5313          18 :   CHECK_EQ(19, a4->Get(context.local(), 2)
    5314             :                    .ToLocalChecked()
    5315             :                    ->Int32Value(context.local())
    5316             :                    .FromJust());
    5317          18 :   CHECK_EQ(20, a4->Get(context.local(), 3)
    5318             :                    .ToLocalChecked()
    5319             :                    ->Int32Value(context.local())
    5320           6 :                    .FromJust());
    5321           6 : }
    5322             : 
    5323             : 
    5324       25881 : THREADED_TEST(FunctionCall) {
    5325           6 :   LocalContext context;
    5326           6 :   v8::Isolate* isolate = context->GetIsolate();
    5327          12 :   v8::HandleScope scope(isolate);
    5328             :   CompileRun(
    5329             :       "function Foo() {"
    5330             :       "  var result = [];"
    5331             :       "  for (var i = 0; i < arguments.length; i++) {"
    5332             :       "    result.push(arguments[i]);"
    5333             :       "  }"
    5334             :       "  return result;"
    5335             :       "}"
    5336             :       "function ReturnThisSloppy() {"
    5337             :       "  return this;"
    5338             :       "}"
    5339             :       "function ReturnThisStrict() {"
    5340             :       "  'use strict';"
    5341             :       "  return this;"
    5342             :       "}");
    5343             :   Local<Function> Foo = Local<Function>::Cast(
    5344          30 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5345             :   Local<Function> ReturnThisSloppy = Local<Function>::Cast(
    5346             :       context->Global()
    5347          24 :           ->Get(context.local(), v8_str("ReturnThisSloppy"))
    5348           6 :           .ToLocalChecked());
    5349             :   Local<Function> ReturnThisStrict = Local<Function>::Cast(
    5350             :       context->Global()
    5351          24 :           ->Get(context.local(), v8_str("ReturnThisStrict"))
    5352           6 :           .ToLocalChecked());
    5353             : 
    5354             :   v8::Local<Value>* args0 = nullptr;
    5355             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5356          12 :       Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
    5357           6 :   CHECK_EQ(0u, a0->Length());
    5358             : 
    5359           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5360             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5361          12 :       Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
    5362           6 :   CHECK_EQ(1u, a1->Length());
    5363          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5364             :                     .ToLocalChecked()
    5365             :                     ->NumberValue(context.local())
    5366             :                     .FromJust());
    5367             : 
    5368           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5369             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5370          12 :       Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
    5371           6 :   CHECK_EQ(2u, a2->Length());
    5372          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5373             :                     .ToLocalChecked()
    5374             :                     ->NumberValue(context.local())
    5375             :                     .FromJust());
    5376          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5377             :                     .ToLocalChecked()
    5378             :                     ->NumberValue(context.local())
    5379             :                     .FromJust());
    5380             : 
    5381           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5382             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5383          12 :       Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
    5384           6 :   CHECK_EQ(3u, a3->Length());
    5385          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5386             :                     .ToLocalChecked()
    5387             :                     ->NumberValue(context.local())
    5388             :                     .FromJust());
    5389          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5390             :                     .ToLocalChecked()
    5391             :                     ->NumberValue(context.local())
    5392             :                     .FromJust());
    5393          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5394             :                     .ToLocalChecked()
    5395             :                     ->NumberValue(context.local())
    5396             :                     .FromJust());
    5397             : 
    5398             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5399           6 :                               v8_num(10.11)};
    5400             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5401          12 :       Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
    5402           6 :   CHECK_EQ(4u, a4->Length());
    5403          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5404             :                     .ToLocalChecked()
    5405             :                     ->NumberValue(context.local())
    5406             :                     .FromJust());
    5407          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5408             :                     .ToLocalChecked()
    5409             :                     ->NumberValue(context.local())
    5410             :                     .FromJust());
    5411          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5412             :                     .ToLocalChecked()
    5413             :                     ->NumberValue(context.local())
    5414             :                     .FromJust());
    5415          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5416             :                       .ToLocalChecked()
    5417             :                       ->NumberValue(context.local())
    5418             :                       .FromJust());
    5419             : 
    5420             :   Local<v8::Value> r1 =
    5421             :       ReturnThisSloppy
    5422          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5423           6 :           .ToLocalChecked();
    5424          12 :   CHECK(r1->StrictEquals(context->Global()));
    5425             :   Local<v8::Value> r2 =
    5426          12 :       ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5427           6 :           .ToLocalChecked();
    5428          12 :   CHECK(r2->StrictEquals(context->Global()));
    5429             :   Local<v8::Value> r3 =
    5430           6 :       ReturnThisSloppy->Call(context.local(), v8_num(42), 0, nullptr)
    5431           6 :           .ToLocalChecked();
    5432           6 :   CHECK(r3->IsNumberObject());
    5433           6 :   CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
    5434             :   Local<v8::Value> r4 =
    5435          18 :       ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, nullptr)
    5436           6 :           .ToLocalChecked();
    5437           6 :   CHECK(r4->IsStringObject());
    5438          18 :   CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
    5439             :   Local<v8::Value> r5 =
    5440          12 :       ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, nullptr)
    5441           6 :           .ToLocalChecked();
    5442           6 :   CHECK(r5->IsBooleanObject());
    5443           6 :   CHECK(r5.As<v8::BooleanObject>()->ValueOf());
    5444             : 
    5445             :   Local<v8::Value> r6 =
    5446             :       ReturnThisStrict
    5447          12 :           ->Call(context.local(), v8::Undefined(isolate), 0, nullptr)
    5448           6 :           .ToLocalChecked();
    5449           6 :   CHECK(r6->IsUndefined());
    5450             :   Local<v8::Value> r7 =
    5451          12 :       ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, nullptr)
    5452           6 :           .ToLocalChecked();
    5453           6 :   CHECK(r7->IsNull());
    5454             :   Local<v8::Value> r8 =
    5455           6 :       ReturnThisStrict->Call(context.local(), v8_num(42), 0, nullptr)
    5456           6 :           .ToLocalChecked();
    5457           6 :   CHECK(r8->StrictEquals(v8_num(42)));
    5458             :   Local<v8::Value> r9 =
    5459          18 :       ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, nullptr)
    5460           6 :           .ToLocalChecked();
    5461          12 :   CHECK(r9->StrictEquals(v8_str("hello")));
    5462             :   Local<v8::Value> r10 =
    5463          12 :       ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, nullptr)
    5464           6 :           .ToLocalChecked();
    5465          12 :   CHECK(r10->StrictEquals(v8::True(isolate)));
    5466           6 : }
    5467             : 
    5468             : 
    5469       25881 : THREADED_TEST(ConstructCall) {
    5470           6 :   LocalContext context;
    5471           6 :   v8::Isolate* isolate = context->GetIsolate();
    5472          12 :   v8::HandleScope scope(isolate);
    5473             :   CompileRun(
    5474             :       "function Foo() {"
    5475             :       "  var result = [];"
    5476             :       "  for (var i = 0; i < arguments.length; i++) {"
    5477             :       "    result.push(arguments[i]);"
    5478             :       "  }"
    5479             :       "  return result;"
    5480             :       "}");
    5481             :   Local<Function> Foo = Local<Function>::Cast(
    5482          30 :       context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
    5483             : 
    5484             :   v8::Local<Value>* args0 = nullptr;
    5485             :   Local<v8::Array> a0 = Local<v8::Array>::Cast(
    5486           6 :       Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
    5487           6 :   CHECK_EQ(0u, a0->Length());
    5488             : 
    5489           6 :   v8::Local<Value> args1[] = {v8_num(1.1)};
    5490             :   Local<v8::Array> a1 = Local<v8::Array>::Cast(
    5491           6 :       Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
    5492           6 :   CHECK_EQ(1u, a1->Length());
    5493          24 :   CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
    5494             :                     .ToLocalChecked()
    5495             :                     ->NumberValue(context.local())
    5496             :                     .FromJust());
    5497             : 
    5498           6 :   v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
    5499             :   Local<v8::Array> a2 = Local<v8::Array>::Cast(
    5500           6 :       Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
    5501           6 :   CHECK_EQ(2u, a2->Length());
    5502          24 :   CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
    5503             :                     .ToLocalChecked()
    5504             :                     ->NumberValue(context.local())
    5505             :                     .FromJust());
    5506          24 :   CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
    5507             :                     .ToLocalChecked()
    5508             :                     ->NumberValue(context.local())
    5509             :                     .FromJust());
    5510             : 
    5511           6 :   v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
    5512             :   Local<v8::Array> a3 = Local<v8::Array>::Cast(
    5513           6 :       Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
    5514           6 :   CHECK_EQ(3u, a3->Length());
    5515          24 :   CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
    5516             :                     .ToLocalChecked()
    5517             :                     ->NumberValue(context.local())
    5518             :                     .FromJust());
    5519          24 :   CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
    5520             :                     .ToLocalChecked()
    5521             :                     ->NumberValue(context.local())
    5522             :                     .FromJust());
    5523          24 :   CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
    5524             :                     .ToLocalChecked()
    5525             :                     ->NumberValue(context.local())
    5526             :                     .FromJust());
    5527             : 
    5528             :   v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
    5529           6 :                               v8_num(10.11)};
    5530             :   Local<v8::Array> a4 = Local<v8::Array>::Cast(
    5531           6 :       Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
    5532           6 :   CHECK_EQ(4u, a4->Length());
    5533          24 :   CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
    5534             :                     .ToLocalChecked()
    5535             :                     ->NumberValue(context.local())
    5536             :                     .FromJust());
    5537          24 :   CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
    5538             :                     .ToLocalChecked()
    5539             :                     ->NumberValue(context.local())
    5540             :                     .FromJust());
    5541          24 :   CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
    5542             :                     .ToLocalChecked()
    5543             :                     ->NumberValue(context.local())
    5544             :                     .FromJust());
    5545          24 :   CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
    5546             :                       .ToLocalChecked()
    5547             :                       ->NumberValue(context.local())
    5548           6 :                       .FromJust());
    5549           6 : }
    5550             : 
    5551             : 
    5552       25881 : THREADED_TEST(ConversionNumber) {
    5553           6 :   LocalContext env;
    5554           6 :   v8::Isolate* isolate = env->GetIsolate();
    5555          12 :   v8::HandleScope scope(isolate);
    5556             :   // Very large number.
    5557             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5558             :   Local<Value> obj =
    5559          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5560          12 :   CHECK_EQ(5312874545152.0,
    5561             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5562          12 :   CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5563          12 :   CHECK_EQ(0, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5564             :   // Large number.
    5565             :   CompileRun("var obj = -1234567890123;");
    5566          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5567          12 :   CHECK_EQ(-1234567890123.0,
    5568             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5569          12 :   CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5570          18 :   CHECK_EQ(2382691125, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5571             :   // Small positive integer.
    5572             :   CompileRun("var obj = 42;");
    5573          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5574          12 :   CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5575          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5576          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5577             :   // Negative integer.
    5578             :   CompileRun("var obj = -37;");
    5579          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5580          12 :   CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5581          12 :   CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5582          18 :   CHECK_EQ(4294967259, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5583             :   // Positive non-int32 integer.
    5584             :   CompileRun("var obj = 0x81234567;");
    5585          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5586          12 :   CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5587          12 :   CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5588          18 :   CHECK_EQ(2166572391, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5589             :   // Fraction.
    5590             :   CompileRun("var obj = 42.3;");
    5591          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5592          12 :   CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5593          12 :   CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5594          12 :   CHECK_EQ(42, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5595             :   // Large negative fraction.
    5596             :   CompileRun("var obj = -5726623061.75;");
    5597          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5598          12 :   CHECK_EQ(-5726623061.75,
    5599             :            obj->ToNumber(env.local()).ToLocalChecked()->Value());
    5600          12 :   CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
    5601          24 :   CHECK_EQ(2863311531, obj->ToUint32(env.local()).ToLocalChecked()->Value());
    5602           6 : }
    5603             : 
    5604             : 
    5605       25881 : THREADED_TEST(isNumberType) {
    5606           6 :   LocalContext env;
    5607          12 :   v8::HandleScope scope(env->GetIsolate());
    5608             :   // Very large number.
    5609             :   CompileRun("var obj = Math.pow(2,32) * 1237;");
    5610             :   Local<Value> obj =
    5611          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5612           6 :   CHECK(!obj->IsInt32());
    5613           6 :   CHECK(!obj->IsUint32());
    5614             :   // Large negative number.
    5615             :   CompileRun("var obj = -1234567890123;");
    5616          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5617           6 :   CHECK(!obj->IsInt32());
    5618           6 :   CHECK(!obj->IsUint32());
    5619             :   // Small positive integer.
    5620             :   CompileRun("var obj = 42;");
    5621          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5622           6 :   CHECK(obj->IsInt32());
    5623           6 :   CHECK(obj->IsUint32());
    5624             :   // Negative integer.
    5625             :   CompileRun("var obj = -37;");
    5626          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5627           6 :   CHECK(obj->IsInt32());
    5628           6 :   CHECK(!obj->IsUint32());
    5629             :   // Positive non-int32 integer.
    5630             :   CompileRun("var obj = 0x81234567;");
    5631          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5632           6 :   CHECK(!obj->IsInt32());
    5633           6 :   CHECK(obj->IsUint32());
    5634             :   // Fraction.
    5635             :   CompileRun("var obj = 42.3;");
    5636          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5637           6 :   CHECK(!obj->IsInt32());
    5638           6 :   CHECK(!obj->IsUint32());
    5639             :   // Large negative fraction.
    5640             :   CompileRun("var obj = -5726623061.75;");
    5641          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5642           6 :   CHECK(!obj->IsInt32());
    5643           6 :   CHECK(!obj->IsUint32());
    5644             :   // Positive zero
    5645             :   CompileRun("var obj = 0.0;");
    5646          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5647           6 :   CHECK(obj->IsInt32());
    5648           6 :   CHECK(obj->IsUint32());
    5649             :   // Negative zero
    5650             :   CompileRun("var obj = -0.0;");
    5651          30 :   obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5652           6 :   CHECK(!obj->IsInt32());
    5653          12 :   CHECK(!obj->IsUint32());
    5654           6 : }
    5655             : 
    5656       25881 : THREADED_TEST(IntegerType) {
    5657           6 :   LocalContext env;
    5658          12 :   v8::HandleScope scope(env->GetIsolate());
    5659             :   Local<Value> result;
    5660             : 
    5661             :   // Small positive integer
    5662             :   result = CompileRun("42;");
    5663           6 :   CHECK(result->IsNumber());
    5664           6 :   CHECK_EQ(42, result.As<v8::Integer>()->Value());
    5665             :   // Small negative integer
    5666             :   result = CompileRun("-42;");
    5667           6 :   CHECK(result->IsNumber());
    5668           6 :   CHECK_EQ(-42, result.As<v8::Integer>()->Value());
    5669             :   // Positive non-int32 integer
    5670             :   result = CompileRun("1099511627776;");
    5671           6 :   CHECK(result->IsNumber());
    5672           6 :   CHECK_EQ(1099511627776, result.As<v8::Integer>()->Value());
    5673             :   // Negative non-int32 integer
    5674             :   result = CompileRun("-1099511627776;");
    5675           6 :   CHECK(result->IsNumber());
    5676           6 :   CHECK_EQ(-1099511627776, result.As<v8::Integer>()->Value());
    5677             :   // Positive non-integer
    5678             :   result = CompileRun("3.14;");
    5679           6 :   CHECK(result->IsNumber());
    5680           6 :   CHECK_EQ(3, result.As<v8::Integer>()->Value());
    5681             :   // Negative non-integer
    5682             :   result = CompileRun("-3.14;");
    5683           6 :   CHECK(result->IsNumber());
    5684          12 :   CHECK_EQ(-3, result.As<v8::Integer>()->Value());
    5685           6 : }
    5686             : 
    5687          54 : static void CheckUncle(v8::Isolate* isolate, v8::TryCatch* try_catch) {
    5688          54 :   CHECK(try_catch->HasCaught());
    5689          54 :   String::Utf8Value str_value(isolate, try_catch->Exception());
    5690          54 :   CHECK_EQ(0, strcmp(*str_value, "uncle?"));
    5691          54 :   try_catch->Reset();
    5692          54 : }
    5693             : 
    5694       25881 : THREADED_TEST(ConversionException) {
    5695           6 :   LocalContext env;
    5696           6 :   v8::Isolate* isolate = env->GetIsolate();
    5697          12 :   v8::HandleScope scope(isolate);
    5698             :   CompileRun(
    5699             :       "function TestClass() { };"
    5700             :       "TestClass.prototype.toString = function () { throw 'uncle?'; };"
    5701             :       "var obj = new TestClass();");
    5702             :   Local<Value> obj =
    5703          30 :       env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
    5704             : 
    5705          12 :   v8::TryCatch try_catch(isolate);
    5706             : 
    5707          12 :   CHECK(obj->ToString(env.local()).IsEmpty());
    5708           6 :   CheckUncle(isolate, &try_catch);
    5709             : 
    5710          12 :   CHECK(obj->ToNumber(env.local()).IsEmpty());
    5711           6 :   CheckUncle(isolate, &try_catch);
    5712             : 
    5713          12 :   CHECK(obj->ToInteger(env.local()).IsEmpty());
    5714           6 :   CheckUncle(isolate, &try_catch);
    5715             : 
    5716          12 :   CHECK(obj->ToUint32(env.local()).IsEmpty());
    5717           6 :   CheckUncle(isolate, &try_catch);
    5718             : 
    5719          12 :   CHECK(obj->ToInt32(env.local()).IsEmpty());
    5720           6 :   CheckUncle(isolate, &try_catch);
    5721             : 
    5722          18 :   CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
    5723           6 :   CHECK(try_catch.HasCaught());
    5724           6 :   try_catch.Reset();
    5725             : 
    5726          12 :   CHECK(obj->Int32Value(env.local()).IsNothing());
    5727           6 :   CheckUncle(isolate, &try_catch);
    5728             : 
    5729          12 :   CHECK(obj->Uint32Value(env.local()).IsNothing());
    5730           6 :   CheckUncle(isolate, &try_catch);
    5731             : 
    5732          12 :   CHECK(obj->NumberValue(env.local()).IsNothing());
    5733           6 :   CheckUncle(isolate, &try_catch);
    5734             : 
    5735          12 :   CHECK(obj->IntegerValue(env.local()).IsNothing());
    5736          12 :   CheckUncle(isolate, &try_catch);
    5737           6 : }
    5738             : 
    5739             : 
    5740          56 : void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5741          28 :   ApiTestFuzzer::Fuzz();
    5742          56 :   args.GetIsolate()->ThrowException(v8_str("konto"));
    5743          28 : }
    5744             : 
    5745             : 
    5746          25 : void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
    5747           5 :   if (args.Length() < 1) {
    5748             :     args.GetReturnValue().Set(false);
    5749           5 :     return;
    5750             :   }
    5751           5 :   v8::HandleScope scope(args.GetIsolate());
    5752          10 :   v8::TryCatch try_catch(args.GetIsolate());
    5753             :   Local<Value> result =
    5754             :       CompileRun(args[0]
    5755           5 :                      ->ToString(args.GetIsolate()->GetCurrentContext())
    5756          10 :                      .ToLocalChecked());
    5757          10 :   CHECK(!try_catch.HasCaught() || result.IsEmpty());
    5758          10 :   args.GetReturnValue().Set(try_catch.HasCaught());
    5759             : }
    5760             : 
    5761             : 
    5762       25881 : THREADED_TEST(APICatch) {
    5763           6 :   v8::Isolate* isolate = CcTest::isolate();
    5764           6 :   v8::HandleScope scope(isolate);
    5765           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5766             :   templ->Set(v8_str("ThrowFromC"),
    5767          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5768          12 :   LocalContext context(nullptr, templ);
    5769             :   CompileRun(
    5770             :       "var thrown = false;"
    5771             :       "try {"
    5772             :       "  ThrowFromC();"
    5773             :       "} catch (e) {"
    5774             :       "  thrown = true;"
    5775             :       "}");
    5776             :   Local<Value> thrown = context->Global()
    5777          24 :                             ->Get(context.local(), v8_str("thrown"))
    5778           6 :                             .ToLocalChecked();
    5779          12 :   CHECK(thrown->BooleanValue(isolate));
    5780           6 : }
    5781             : 
    5782             : 
    5783       25881 : THREADED_TEST(APIThrowTryCatch) {
    5784           6 :   v8::Isolate* isolate = CcTest::isolate();
    5785           6 :   v8::HandleScope scope(isolate);
    5786           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5787             :   templ->Set(v8_str("ThrowFromC"),
    5788          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5789          12 :   LocalContext context(nullptr, templ);
    5790          12 :   v8::TryCatch try_catch(isolate);
    5791             :   CompileRun("ThrowFromC();");
    5792          12 :   CHECK(try_catch.HasCaught());
    5793           6 : }
    5794             : 
    5795             : 
    5796             : // Test that a try-finally block doesn't shadow a try-catch block
    5797             : // when setting up an external handler.
    5798             : //
    5799             : // BUG(271): Some of the exception propagation does not work on the
    5800             : // ARM simulator because the simulator separates the C++ stack and the
    5801             : // JS stack.  This test therefore fails on the simulator.  The test is
    5802             : // not threaded to allow the threading tests to run on the simulator.
    5803       25880 : TEST(TryCatchInTryFinally) {
    5804           5 :   v8::Isolate* isolate = CcTest::isolate();
    5805           5 :   v8::HandleScope scope(isolate);
    5806           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5807          15 :   templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
    5808          10 :   LocalContext context(nullptr, templ);
    5809             :   Local<Value> result = CompileRun(
    5810             :       "try {"
    5811             :       "  try {"
    5812             :       "    CCatcher('throw 7;');"
    5813             :       "  } finally {"
    5814             :       "  }"
    5815             :       "} catch (e) {"
    5816             :       "}");
    5817          10 :   CHECK(result->IsTrue());
    5818           5 : }
    5819             : 
    5820             : 
    5821           5 : static void check_custom_error_tostring(v8::Local<v8::Message> message,
    5822             :                                         v8::Local<v8::Value> data) {
    5823             :   const char* uncaught_error = "Uncaught MyError toString";
    5824          25 :   CHECK(message->Get()
    5825             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5826             :                      v8_str(uncaught_error))
    5827             :             .FromJust());
    5828           5 : }
    5829             : 
    5830             : 
    5831       25880 : TEST(CustomErrorToString) {
    5832           5 :   LocalContext context;
    5833          10 :   v8::HandleScope scope(context->GetIsolate());
    5834           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
    5835             :   CompileRun(
    5836             :       "function MyError(name, message) {                   "
    5837             :       "  this.name = name;                                 "
    5838             :       "  this.message = message;                           "
    5839             :       "}                                                   "
    5840             :       "MyError.prototype = Object.create(Error.prototype); "
    5841             :       "MyError.prototype.toString = function() {           "
    5842             :       "  return 'MyError toString';                        "
    5843             :       "};                                                  "
    5844             :       "throw new MyError('my name', 'my message');         ");
    5845          10 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
    5846           5 : }
    5847             : 
    5848             : 
    5849          15 : static void check_custom_error_message(v8::Local<v8::Message> message,
    5850             :                                        v8::Local<v8::Value> data) {
    5851             :   const char* uncaught_error = "Uncaught MyError: my message";
    5852          45 :   printf("%s\n", *v8::String::Utf8Value(CcTest::isolate(), message->Get()));
    5853          60 :   CHECK(message->Get()
    5854             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5855             :                      v8_str(uncaught_error))
    5856             :             .FromJust());
    5857          15 : }
    5858             : 
    5859             : 
    5860       25880 : TEST(CustomErrorMessage) {
    5861           5 :   LocalContext context;
    5862          10 :   v8::HandleScope scope(context->GetIsolate());
    5863           5 :   context->GetIsolate()->AddMessageListener(check_custom_error_message);
    5864             : 
    5865             :   // Handlebars.
    5866             :   CompileRun(
    5867             :       "function MyError(msg) {                             "
    5868             :       "  this.name = 'MyError';                            "
    5869             :       "  this.message = msg;                               "
    5870             :       "}                                                   "
    5871             :       "MyError.prototype = new Error();                    "
    5872             :       "throw new MyError('my message');                    ");
    5873             : 
    5874             :   // Closure.
    5875             :   CompileRun(
    5876             :       "function MyError(msg) {                             "
    5877             :       "  this.name = 'MyError';                            "
    5878             :       "  this.message = msg;                               "
    5879             :       "}                                                   "
    5880             :       "inherits = function(childCtor, parentCtor) {        "
    5881             :       "    function tempCtor() {};                         "
    5882             :       "    tempCtor.prototype = parentCtor.prototype;      "
    5883             :       "    childCtor.superClass_ = parentCtor.prototype;   "
    5884             :       "    childCtor.prototype = new tempCtor();           "
    5885             :       "    childCtor.prototype.constructor = childCtor;    "
    5886             :       "};                                                  "
    5887             :       "inherits(MyError, Error);                           "
    5888             :       "throw new MyError('my message');                    ");
    5889             : 
    5890             :   // Object.create.
    5891             :   CompileRun(
    5892             :       "function MyError(msg) {                             "
    5893             :       "  this.name = 'MyError';                            "
    5894             :       "  this.message = msg;                               "
    5895             :       "}                                                   "
    5896             :       "MyError.prototype = Object.create(Error.prototype); "
    5897             :       "throw new MyError('my message');                    ");
    5898             : 
    5899          10 :   context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
    5900           5 : }
    5901             : 
    5902             : 
    5903          10 : static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
    5904             :                                             v8::Local<v8::Value> data) {
    5905          10 :   CHECK(data->IsExternal());
    5906          10 :   int* callcount = static_cast<int*>(data.As<v8::External>()->Value());
    5907          10 :   ++*callcount;
    5908             : 
    5909             :   const char* uncaught_error = "Uncaught exception";
    5910          50 :   CHECK(message->Get()
    5911             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5912             :                      v8_str(uncaught_error))
    5913             :             .FromJust());
    5914             :   // Test that compiling code inside a message handler works.
    5915          40 :   CHECK(CompileRunChecked(CcTest::isolate(), "(function(a) { return a; })(42)")
    5916             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
    5917             :                      v8::Integer::NewFromUnsigned(CcTest::isolate(), 42))
    5918             :             .FromJust());
    5919          10 : }
    5920             : 
    5921             : 
    5922       25880 : TEST(CustomErrorRethrowsOnToString) {
    5923           5 :   int callcount = 0;
    5924           5 :   LocalContext context;
    5925           5 :   v8::Isolate* isolate = context->GetIsolate();
    5926          10 :   v8::HandleScope scope(isolate);
    5927             :   context->GetIsolate()->AddMessageListener(
    5928          10 :       check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
    5929             : 
    5930             :   CompileRun(
    5931             :       "var e = { toString: function() { throw e; } };"
    5932             :       "try { throw e; } finally {}");
    5933             : 
    5934           5 :   CHECK_EQ(callcount, 1);
    5935             :   context->GetIsolate()->RemoveMessageListeners(
    5936          10 :       check_custom_rethrowing_message);
    5937           5 : }
    5938             : 
    5939       25880 : TEST(CustomErrorRethrowsOnToStringInsideVerboseTryCatch) {
    5940           5 :   int callcount = 0;
    5941           5 :   LocalContext context;
    5942           5 :   v8::Isolate* isolate = context->GetIsolate();
    5943          10 :   v8::HandleScope scope(isolate);
    5944          10 :   v8::TryCatch try_catch(isolate);
    5945           5 :   try_catch.SetVerbose(true);
    5946             :   context->GetIsolate()->AddMessageListener(
    5947          10 :       check_custom_rethrowing_message, v8::External::New(isolate, &callcount));
    5948             : 
    5949             :   CompileRun(
    5950             :       "var e = { toString: function() { throw e; } };"
    5951             :       "try { throw e; } finally {}");
    5952             : 
    5953           5 :   CHECK_EQ(callcount, 1);
    5954             :   context->GetIsolate()->RemoveMessageListeners(
    5955          10 :       check_custom_rethrowing_message);
    5956           5 : }
    5957             : 
    5958             : 
    5959          15 : static void receive_message(v8::Local<v8::Message> message,
    5960             :                             v8::Local<v8::Value> data) {
    5961          15 :   message->Get();
    5962          15 :   message_received = true;
    5963          15 : }
    5964             : 
    5965             : 
    5966       25880 : TEST(APIThrowMessage) {
    5967           5 :   message_received = false;
    5968           5 :   v8::Isolate* isolate = CcTest::isolate();
    5969           5 :   v8::HandleScope scope(isolate);
    5970           5 :   isolate->AddMessageListener(receive_message);
    5971           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5972             :   templ->Set(v8_str("ThrowFromC"),
    5973          15 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5974          10 :   LocalContext context(nullptr, templ);
    5975             :   CompileRun("ThrowFromC();");
    5976           5 :   CHECK(message_received);
    5977          10 :   isolate->RemoveMessageListeners(receive_message);
    5978           5 : }
    5979             : 
    5980             : 
    5981       25880 : TEST(APIThrowMessageAndVerboseTryCatch) {
    5982           5 :   message_received = false;
    5983           5 :   v8::Isolate* isolate = CcTest::isolate();
    5984           5 :   v8::HandleScope scope(isolate);
    5985           5 :   isolate->AddMessageListener(receive_message);
    5986           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    5987             :   templ->Set(v8_str("ThrowFromC"),
    5988          15 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    5989          10 :   LocalContext context(nullptr, templ);
    5990          10 :   v8::TryCatch try_catch(isolate);
    5991           5 :   try_catch.SetVerbose(true);
    5992             :   Local<Value> result = CompileRun("ThrowFromC();");
    5993           5 :   CHECK(try_catch.HasCaught());
    5994           5 :   CHECK(result.IsEmpty());
    5995           5 :   CHECK(message_received);
    5996          10 :   isolate->RemoveMessageListeners(receive_message);
    5997           5 : }
    5998             : 
    5999             : 
    6000       25880 : TEST(APIStackOverflowAndVerboseTryCatch) {
    6001           5 :   message_received = false;
    6002           5 :   LocalContext context;
    6003          10 :   v8::HandleScope scope(context->GetIsolate());
    6004           5 :   context->GetIsolate()->AddMessageListener(receive_message);
    6005          10 :   v8::TryCatch try_catch(context->GetIsolate());
    6006           5 :   try_catch.SetVerbose(true);
    6007             :   Local<Value> result = CompileRun("function foo() { foo(); } foo();");
    6008           5 :   CHECK(try_catch.HasCaught());
    6009           5 :   CHECK(result.IsEmpty());
    6010           5 :   CHECK(message_received);
    6011          10 :   context->GetIsolate()->RemoveMessageListeners(receive_message);
    6012           5 : }
    6013             : 
    6014             : 
    6015       25881 : THREADED_TEST(ExternalScriptException) {
    6016           6 :   v8::Isolate* isolate = CcTest::isolate();
    6017           6 :   v8::HandleScope scope(isolate);
    6018           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6019             :   templ->Set(v8_str("ThrowFromC"),
    6020          18 :              v8::FunctionTemplate::New(isolate, ThrowFromC));
    6021          12 :   LocalContext context(nullptr, templ);
    6022             : 
    6023          12 :   v8::TryCatch try_catch(isolate);
    6024             :   Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
    6025           6 :   CHECK(result.IsEmpty());
    6026           6 :   CHECK(try_catch.HasCaught());
    6027          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6028          12 :   CHECK_EQ(0, strcmp("konto", *exception_value));
    6029           6 : }
    6030             : 
    6031             : 
    6032         370 : void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6033          85 :   ApiTestFuzzer::Fuzz();
    6034          85 :   CHECK_EQ(4, args.Length());
    6035          85 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    6036         170 :   int count = args[0]->Int32Value(context).FromJust();
    6037         170 :   int cInterval = args[2]->Int32Value(context).FromJust();
    6038          85 :   if (count == 0) {
    6039          10 :     args.GetIsolate()->ThrowException(v8_str("FromC"));
    6040           5 :     return;
    6041             :   } else {
    6042          80 :     Local<v8::Object> global = context->Global();
    6043             :     Local<Value> fun =
    6044         240 :         global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
    6045         320 :     v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
    6046          80 :     if (count % cInterval == 0) {
    6047          30 :       v8::TryCatch try_catch(args.GetIsolate());
    6048             :       Local<Value> result = fun.As<Function>()
    6049          30 :                                 ->Call(context, global, 4, argv)
    6050          60 :                                 .FromMaybe(Local<Value>());
    6051          60 :       int expected = args[3]->Int32Value(context).FromJust();
    6052          30 :       if (try_catch.HasCaught()) {
    6053          15 :         CHECK_EQ(expected, count);
    6054          15 :         CHECK(result.IsEmpty());
    6055          15 :         CHECK(!CcTest::i_isolate()->has_scheduled_exception());
    6056             :       } else {
    6057          15 :         CHECK_NE(expected, count);
    6058             :       }
    6059             :       args.GetReturnValue().Set(result);
    6060          30 :       return;
    6061             :     } else {
    6062             :       args.GetReturnValue().Set(fun.As<Function>()
    6063          50 :                                     ->Call(context, global, 4, argv)
    6064         100 :                                     .FromMaybe(v8::Local<v8::Value>()));
    6065          50 :       return;
    6066             :     }
    6067             :   }
    6068             : }
    6069             : 
    6070             : 
    6071          75 : void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6072          25 :   ApiTestFuzzer::Fuzz();
    6073          25 :   CHECK_EQ(3, args.Length());
    6074             :   v8::Isolate* isolate = args.GetIsolate();
    6075          25 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
    6076          25 :   bool equality = args[0]->BooleanValue(isolate);
    6077          50 :   int count = args[1]->Int32Value(context).FromJust();
    6078          50 :   int expected = args[2]->Int32Value(context).FromJust();
    6079          25 :   if (equality) {
    6080          15 :     CHECK_EQ(count, expected);
    6081             :   } else {
    6082          10 :     CHECK_NE(count, expected);
    6083             :   }
    6084          25 : }
    6085             : 
    6086             : 
    6087       25881 : THREADED_TEST(EvalInTryFinally) {
    6088           6 :   LocalContext context;
    6089          12 :   v8::HandleScope scope(context->GetIsolate());
    6090          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6091             :   CompileRun(
    6092             :       "(function() {"
    6093             :       "  try {"
    6094             :       "    eval('asldkf (*&^&*^');"
    6095             :       "  } finally {"
    6096             :       "    return;"
    6097             :       "  }"
    6098             :       "})()");
    6099          12 :   CHECK(!try_catch.HasCaught());
    6100           6 : }
    6101             : 
    6102             : 
    6103             : // This test works by making a stack of alternating JavaScript and C
    6104             : // activations.  These activations set up exception handlers with regular
    6105             : // intervals, one interval for C activations and another for JavaScript
    6106             : // activations.  When enough activations have been created an exception is
    6107             : // thrown and we check that the right activation catches the exception and that
    6108             : // no other activations do.  The right activation is always the topmost one with
    6109             : // a handler, regardless of whether it is in JavaScript or C.
    6110             : //
    6111             : // The notation used to describe a test case looks like this:
    6112             : //
    6113             : //    *JS[4] *C[3] @JS[2] C[1] JS[0]
    6114             : //
    6115             : // Each entry is an activation, either JS or C.  The index is the count at that
    6116             : // level.  Stars identify activations with exception handlers, the @ identifies
    6117             : // the exception handler that should catch the exception.
    6118             : //
    6119             : // BUG(271): Some of the exception propagation does not work on the
    6120             : // ARM simulator because the simulator separates the C++ stack and the
    6121             : // JS stack.  This test therefore fails on the simulator.  The test is
    6122             : // not threaded to allow the threading tests to run on the simulator.
    6123       25880 : TEST(ExceptionOrder) {
    6124           5 :   v8::Isolate* isolate = CcTest::isolate();
    6125           5 :   v8::HandleScope scope(isolate);
    6126           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6127          15 :   templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
    6128             :   templ->Set(v8_str("CThrowCountDown"),
    6129          15 :              v8::FunctionTemplate::New(isolate, CThrowCountDown));
    6130          10 :   LocalContext context(nullptr, templ);
    6131             :   CompileRun(
    6132             :       "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
    6133             :       "  if (count == 0) throw 'FromJS';"
    6134             :       "  if (count % jsInterval == 0) {"
    6135             :       "    try {"
    6136             :       "      var value = CThrowCountDown(count - 1,"
    6137             :       "                                  jsInterval,"
    6138             :       "                                  cInterval,"
    6139             :       "                                  expected);"
    6140             :       "      check(false, count, expected);"
    6141             :       "      return value;"
    6142             :       "    } catch (e) {"
    6143             :       "      check(true, count, expected);"
    6144             :       "    }"
    6145             :       "  } else {"
    6146             :       "    return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
    6147             :       "  }"
    6148             :       "}");
    6149             :   Local<Function> fun = Local<Function>::Cast(
    6150             :       context->Global()
    6151          20 :           ->Get(context.local(), v8_str("JSThrowCountDown"))
    6152           5 :           .ToLocalChecked());
    6153             : 
    6154             :   const int argc = 4;
    6155             :   //                             count      jsInterval cInterval  expected
    6156             : 
    6157             :   // *JS[4] *C[3] @JS[2] C[1] JS[0]
    6158           5 :   v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
    6159          10 :   fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
    6160             : 
    6161             :   // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
    6162           5 :   v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
    6163          10 :   fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
    6164             : 
    6165             :   // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6166           5 :   v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
    6167          10 :   fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
    6168             : 
    6169             :   // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
    6170           5 :   v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
    6171          10 :   fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
    6172             : 
    6173             :   // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
    6174           5 :   v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
    6175          10 :   fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
    6176             : 
    6177             :   // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
    6178           5 :   v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
    6179          15 :   fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
    6180           5 : }
    6181             : 
    6182             : 
    6183         126 : void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6184          42 :   ApiTestFuzzer::Fuzz();
    6185          42 :   CHECK_EQ(1, args.Length());
    6186          42 :   args.GetIsolate()->ThrowException(args[0]);
    6187          42 : }
    6188             : 
    6189             : 
    6190       25881 : THREADED_TEST(ThrowValues) {
    6191           6 :   v8::Isolate* isolate = CcTest::isolate();
    6192           6 :   v8::HandleScope scope(isolate);
    6193           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6194          18 :   templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
    6195          12 :   LocalContext context(nullptr, templ);
    6196             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
    6197             :       CompileRun("function Run(obj) {"
    6198             :                  "  try {"
    6199             :                  "    Throw(obj);"
    6200             :                  "  } catch (e) {"
    6201             :                  "    return e;"
    6202             :                  "  }"
    6203             :                  "  return 'no exception';"
    6204             :                  "}"
    6205             :                  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
    6206           6 :   CHECK_EQ(5u, result->Length());
    6207          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
    6208             :             .ToLocalChecked()
    6209             :             ->IsString());
    6210          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
    6211             :             .ToLocalChecked()
    6212             :             ->IsNumber());
    6213          24 :   CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
    6214             :                   .ToLocalChecked()
    6215             :                   ->Int32Value(context.local())
    6216             :                   .FromJust());
    6217          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
    6218             :             .ToLocalChecked()
    6219             :             ->IsNumber());
    6220          24 :   CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
    6221             :                   .ToLocalChecked()
    6222             :                   ->Int32Value(context.local())
    6223             :                   .FromJust());
    6224          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
    6225             :             .ToLocalChecked()
    6226             :             ->IsNull());
    6227          18 :   CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
    6228             :             .ToLocalChecked()
    6229           6 :             ->IsUndefined());
    6230           6 : }
    6231             : 
    6232             : 
    6233       25881 : THREADED_TEST(CatchZero) {
    6234           6 :   LocalContext context;
    6235          12 :   v8::HandleScope scope(context->GetIsolate());
    6236          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6237           6 :   CHECK(!try_catch.HasCaught());
    6238             :   CompileRun("throw 10");
    6239           6 :   CHECK(try_catch.HasCaught());
    6240          18 :   CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6241           6 :   try_catch.Reset();
    6242           6 :   CHECK(!try_catch.HasCaught());
    6243             :   CompileRun("throw 0");
    6244           6 :   CHECK(try_catch.HasCaught());
    6245          24 :   CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
    6246           6 : }
    6247             : 
    6248             : 
    6249       25881 : THREADED_TEST(CatchExceptionFromWith) {
    6250           6 :   LocalContext context;
    6251          12 :   v8::HandleScope scope(context->GetIsolate());
    6252          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6253           6 :   CHECK(!try_catch.HasCaught());
    6254             :   CompileRun("var o = {}; with (o) { throw 42; }");
    6255          12 :   CHECK(try_catch.HasCaught());
    6256           6 : }
    6257             : 
    6258             : 
    6259       25881 : THREADED_TEST(TryCatchAndFinallyHidingException) {
    6260           6 :   LocalContext context;
    6261          12 :   v8::HandleScope scope(context->GetIsolate());
    6262          12 :   v8::TryCatch try_catch(context->GetIsolate());
    6263           6 :   CHECK(!try_catch.HasCaught());
    6264             :   CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
    6265             :   CompileRun("f({toString: function() { throw 42; }});");
    6266          12 :   CHECK(!try_catch.HasCaught());
    6267           6 : }
    6268             : 
    6269             : 
    6270           6 : void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6271           6 :   v8::TryCatch try_catch(args.GetIsolate());
    6272           6 : }
    6273             : 
    6274             : 
    6275       25881 : THREADED_TEST(TryCatchAndFinally) {
    6276           6 :   LocalContext context;
    6277           6 :   v8::Isolate* isolate = context->GetIsolate();
    6278          12 :   v8::HandleScope scope(isolate);
    6279          48 :   CHECK(context->Global()
    6280             :             ->Set(context.local(), v8_str("native_with_try_catch"),
    6281             :                   v8::FunctionTemplate::New(isolate, WithTryCatch)
    6282             :                       ->GetFunction(context.local())
    6283             :                       .ToLocalChecked())
    6284             :             .FromJust());
    6285          12 :   v8::TryCatch try_catch(isolate);
    6286           6 :   CHECK(!try_catch.HasCaught());
    6287             :   CompileRun(
    6288             :       "try {\n"
    6289             :       "  throw new Error('a');\n"
    6290             :       "} finally {\n"
    6291             :       "  native_with_try_catch();\n"
    6292             :       "}\n");
    6293          12 :   CHECK(try_catch.HasCaught());
    6294           6 : }
    6295             : 
    6296             : 
    6297          30 : static void TryCatchNested1Helper(int depth) {
    6298          30 :   if (depth > 0) {
    6299          25 :     v8::TryCatch try_catch(CcTest::isolate());
    6300          25 :     try_catch.SetVerbose(true);
    6301          25 :     TryCatchNested1Helper(depth - 1);
    6302          25 :     CHECK(try_catch.HasCaught());
    6303          25 :     try_catch.ReThrow();
    6304             :   } else {
    6305          10 :     CcTest::isolate()->ThrowException(v8_str("E1"));
    6306             :   }
    6307          30 : }
    6308             : 
    6309             : 
    6310          30 : static void TryCatchNested2Helper(int depth) {
    6311          30 :   if (depth > 0) {
    6312          25 :     v8::TryCatch try_catch(CcTest::isolate());
    6313          25 :     try_catch.SetVerbose(true);
    6314          25 :     TryCatchNested2Helper(depth - 1);
    6315          25 :     CHECK(try_catch.HasCaught());
    6316          25 :     try_catch.ReThrow();
    6317             :   } else {
    6318             :     CompileRun("throw 'E2';");
    6319             :   }
    6320          30 : }
    6321             : 
    6322             : 
    6323       25880 : TEST(TryCatchNested) {
    6324           5 :   v8::V8::Initialize();
    6325           5 :   LocalContext context;
    6326          10 :   v8::HandleScope scope(context->GetIsolate());
    6327             : 
    6328             :   {
    6329             :     // Test nested try-catch with a native throw in the end.
    6330           5 :     v8::TryCatch try_catch(context->GetIsolate());
    6331           5 :     TryCatchNested1Helper(5);
    6332           5 :     CHECK(try_catch.HasCaught());
    6333          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6334             :                                               try_catch.Exception()),
    6335           5 :                        "E1"));
    6336             :   }
    6337             : 
    6338             :   {
    6339             :     // Test nested try-catch with a JavaScript throw in the end.
    6340           5 :     v8::TryCatch try_catch(context->GetIsolate());
    6341           5 :     TryCatchNested2Helper(5);
    6342           5 :     CHECK(try_catch.HasCaught());
    6343          10 :     CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(),
    6344             :                                               try_catch.Exception()),
    6345           5 :                        "E2"));
    6346           5 :   }
    6347           5 : }
    6348             : 
    6349             : 
    6350          10 : void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
    6351          10 :   CHECK(try_catch->HasCaught());
    6352          10 :   Local<Message> message = try_catch->Message();
    6353          10 :   Local<Value> resource = message->GetScriptOrigin().ResourceName();
    6354          10 :   CHECK_EQ(
    6355             :       0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), resource), "inner"));
    6356          20 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(CcTest::isolate(), message->Get()),
    6357             :                      "Uncaught Error: a"));
    6358          20 :   CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
    6359             :                   .FromJust());
    6360          20 :   CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
    6361             :                   .FromJust());
    6362          10 : }
    6363             : 
    6364             : 
    6365           5 : void TryCatchMixedNestingHelper(
    6366           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6367           5 :   ApiTestFuzzer::Fuzz();
    6368           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6369           5 :   CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
    6370           5 :   CHECK(try_catch.HasCaught());
    6371           5 :   TryCatchMixedNestingCheck(&try_catch);
    6372           5 :   try_catch.ReThrow();
    6373           5 : }
    6374             : 
    6375             : 
    6376             : // This test ensures that an outer TryCatch in the following situation:
    6377             : //   C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
    6378             : // does not clobber the Message object generated for the inner TryCatch.
    6379             : // This exercises the ability of TryCatch.ReThrow() to restore the
    6380             : // inner pending Message before throwing the exception again.
    6381       25880 : TEST(TryCatchMixedNesting) {
    6382           5 :   v8::Isolate* isolate = CcTest::isolate();
    6383           5 :   v8::HandleScope scope(isolate);
    6384           5 :   v8::V8::Initialize();
    6385          10 :   v8::TryCatch try_catch(isolate);
    6386           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6387             :   templ->Set(v8_str("TryCatchMixedNestingHelper"),
    6388          15 :              v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
    6389          10 :   LocalContext context(nullptr, templ);
    6390           5 :   CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
    6391          10 :   TryCatchMixedNestingCheck(&try_catch);
    6392           5 : }
    6393             : 
    6394             : 
    6395          15 : void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
    6396           5 :   ApiTestFuzzer::Fuzz();
    6397           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6398          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6399           5 :   CHECK(try_catch.HasCaught());
    6400           5 : }
    6401             : 
    6402             : 
    6403       25880 : TEST(TryCatchNative) {
    6404           5 :   v8::Isolate* isolate = CcTest::isolate();
    6405           5 :   v8::HandleScope scope(isolate);
    6406           5 :   v8::V8::Initialize();
    6407          10 :   v8::TryCatch try_catch(isolate);
    6408           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6409             :   templ->Set(v8_str("TryCatchNativeHelper"),
    6410          15 :              v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
    6411          10 :   LocalContext context(nullptr, templ);
    6412             :   CompileRun("TryCatchNativeHelper();");
    6413          10 :   CHECK(!try_catch.HasCaught());
    6414           5 : }
    6415             : 
    6416             : 
    6417           5 : void TryCatchNativeResetHelper(
    6418          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    6419           5 :   ApiTestFuzzer::Fuzz();
    6420           5 :   v8::TryCatch try_catch(args.GetIsolate());
    6421          10 :   args.GetIsolate()->ThrowException(v8_str("boom"));
    6422           5 :   CHECK(try_catch.HasCaught());
    6423           5 :   try_catch.Reset();
    6424           5 :   CHECK(!try_catch.HasCaught());
    6425           5 : }
    6426             : 
    6427             : 
    6428       25880 : TEST(TryCatchNativeReset) {
    6429           5 :   v8::Isolate* isolate = CcTest::isolate();
    6430           5 :   v8::HandleScope scope(isolate);
    6431           5 :   v8::V8::Initialize();
    6432          10 :   v8::TryCatch try_catch(isolate);
    6433           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6434             :   templ->Set(v8_str("TryCatchNativeResetHelper"),
    6435          15 :              v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
    6436          10 :   LocalContext context(nullptr, templ);
    6437             :   CompileRun("TryCatchNativeResetHelper();");
    6438          10 :   CHECK(!try_catch.HasCaught());
    6439           5 : }
    6440             : 
    6441             : 
    6442       25881 : THREADED_TEST(Equality) {
    6443           6 :   LocalContext context;
    6444           6 :   v8::Isolate* isolate = context->GetIsolate();
    6445          12 :   v8::HandleScope scope(context->GetIsolate());
    6446             :   // Check that equality works at all before relying on CHECK_EQ
    6447          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6448          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6449             : 
    6450          24 :   CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
    6451          24 :   CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
    6452          18 :   CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
    6453          18 :   CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
    6454          18 :   CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
    6455             : 
    6456             :   // Assume String is not internalized.
    6457          18 :   CHECK(v8_str("a")->StrictEquals(v8_str("a")));
    6458          18 :   CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
    6459          12 :   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
    6460          12 :   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
    6461          12 :   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
    6462          12 :   CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
    6463           6 :   Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
    6464           6 :   CHECK(!not_a_number->StrictEquals(not_a_number));
    6465           6 :   CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
    6466           6 :   CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
    6467             : 
    6468           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    6469             :   v8::Persistent<v8::Object> alias(isolate, obj);
    6470           6 :   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
    6471             :   alias.Reset();
    6472             : 
    6473          18 :   CHECK(v8_str("a")->SameValue(v8_str("a")));
    6474          18 :   CHECK(!v8_str("a")->SameValue(v8_str("b")));
    6475          12 :   CHECK(!v8_str("5")->SameValue(v8_num(5)));
    6476          12 :   CHECK(v8_num(1)->SameValue(v8_num(1)));
    6477          12 :   CHECK(!v8_num(1)->SameValue(v8_num(2)));
    6478          12 :   CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
    6479           6 :   CHECK(not_a_number->SameValue(not_a_number));
    6480           6 :   CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
    6481          12 :   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
    6482           6 : }
    6483             : 
    6484       25881 : THREADED_TEST(TypeOf) {
    6485           6 :   LocalContext context;
    6486           6 :   v8::Isolate* isolate = context->GetIsolate();
    6487          12 :   v8::HandleScope scope(context->GetIsolate());
    6488             : 
    6489           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
    6490          12 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
    6491             : 
    6492          30 :   CHECK(v8::Undefined(isolate)
    6493             :             ->TypeOf(isolate)
    6494             :             ->Equals(context.local(), v8_str("undefined"))
    6495             :             .FromJust());
    6496          30 :   CHECK(v8::Null(isolate)
    6497             :             ->TypeOf(isolate)
    6498             :             ->Equals(context.local(), v8_str("object"))
    6499             :             .FromJust());
    6500          30 :   CHECK(v8_str("str")
    6501             :             ->TypeOf(isolate)
    6502             :             ->Equals(context.local(), v8_str("string"))
    6503             :             .FromJust());
    6504          30 :   CHECK(v8_num(0.0)
    6505             :             ->TypeOf(isolate)
    6506             :             ->Equals(context.local(), v8_str("number"))
    6507             :             .FromJust());
    6508          30 :   CHECK(v8_num(1)
    6509             :             ->TypeOf(isolate)
    6510             :             ->Equals(context.local(), v8_str("number"))
    6511             :             .FromJust());
    6512          30 :   CHECK(v8::Object::New(isolate)
    6513             :             ->TypeOf(isolate)
    6514             :             ->Equals(context.local(), v8_str("object"))
    6515             :             .FromJust());
    6516          30 :   CHECK(v8::Boolean::New(isolate, true)
    6517             :             ->TypeOf(isolate)
    6518             :             ->Equals(context.local(), v8_str("boolean"))
    6519             :             .FromJust());
    6520          24 :   CHECK(fun->TypeOf(isolate)
    6521             :             ->Equals(context.local(), v8_str("function"))
    6522           6 :             .FromJust());
    6523           6 : }
    6524             : 
    6525       25881 : THREADED_TEST(InstanceOf) {
    6526           6 :   LocalContext env;
    6527          12 :   v8::HandleScope scope(env->GetIsolate());
    6528             :   CompileRun(
    6529             :       "var A = {};"
    6530             :       "var B = {};"
    6531             :       "var C = {};"
    6532             :       "B.__proto__ = A;"
    6533             :       "C.__proto__ = B;"
    6534             :       "function F() {}"
    6535             :       "F.prototype = A;"
    6536             :       "var G = { [Symbol.hasInstance] : null};"
    6537             :       "var H = { [Symbol.hasInstance] : () => { throw new Error(); } };"
    6538             :       "var J = { [Symbol.hasInstance] : () => true };"
    6539             :       "class K {}"
    6540             :       "var D = new K;"
    6541             :       "class L extends K {}"
    6542             :       "var E = new L");
    6543             : 
    6544           6 :   v8::Local<v8::Object> f = v8::Local<v8::Object>::Cast(CompileRun("F"));
    6545           6 :   v8::Local<v8::Object> g = v8::Local<v8::Object>::Cast(CompileRun("G"));
    6546           6 :   v8::Local<v8::Object> h = v8::Local<v8::Object>::Cast(CompileRun("H"));
    6547           6 :   v8::Local<v8::Object> j = v8::Local<v8::Object>::Cast(CompileRun("J"));
    6548           6 :   v8::Local<v8::Object> k = v8::Local<v8::Object>::Cast(CompileRun("K"));
    6549           6 :   v8::Local<v8::Object> l = v8::Local<v8::Object>::Cast(CompileRun("L"));
    6550             :   v8::Local<v8::Value> a = v8::Local<v8::Value>::Cast(CompileRun("A"));
    6551             :   v8::Local<v8::Value> b = v8::Local<v8::Value>::Cast(CompileRun("B"));
    6552             :   v8::Local<v8::Value> c = v8::Local<v8::Value>::Cast(CompileRun("C"));
    6553             :   v8::Local<v8::Value> d = v8::Local<v8::Value>::Cast(CompileRun("D"));
    6554             :   v8::Local<v8::Value> e = v8::Local<v8::Value>::Cast(CompileRun("E"));
    6555             : 
    6556          12 :   v8::TryCatch try_catch(env->GetIsolate());
    6557          12 :   CHECK(!a->InstanceOf(env.local(), f).ToChecked());
    6558          12 :   CHECK(b->InstanceOf(env.local(), f).ToChecked());
    6559          12 :   CHECK(c->InstanceOf(env.local(), f).ToChecked());
    6560          12 :   CHECK(!d->InstanceOf(env.local(), f).ToChecked());
    6561          12 :   CHECK(!e->InstanceOf(env.local(), f).ToChecked());
    6562           6 :   CHECK(!try_catch.HasCaught());
    6563             : 
    6564          12 :   CHECK(a->InstanceOf(env.local(), g).IsNothing());
    6565           6 :   CHECK(try_catch.HasCaught());
    6566           6 :   try_catch.Reset();
    6567             : 
    6568          12 :   CHECK(b->InstanceOf(env.local(), h).IsNothing());
    6569           6 :   CHECK(try_catch.HasCaught());
    6570           6 :   try_catch.Reset();
    6571             : 
    6572          18 :   CHECK(v8_num(1)->InstanceOf(env.local(), j).ToChecked());
    6573           6 :   CHECK(!try_catch.HasCaught());
    6574             : 
    6575          12 :   CHECK(d->InstanceOf(env.local(), k).ToChecked());
    6576          12 :   CHECK(e->InstanceOf(env.local(), k).ToChecked());
    6577          12 :   CHECK(!d->InstanceOf(env.local(), l).ToChecked());
    6578          12 :   CHECK(e->InstanceOf(env.local(), l).ToChecked());
    6579          12 :   CHECK(!try_catch.HasCaught());
    6580           6 : }
    6581             : 
    6582       25881 : THREADED_TEST(MultiRun) {
    6583           6 :   LocalContext context;
    6584          12 :   v8::HandleScope scope(context->GetIsolate());
    6585             :   Local<Script> script = v8_compile("x");
    6586          66 :   for (int i = 0; i < 10; i++) {
    6587          60 :     script->Run(context.local()).IsEmpty();
    6588           6 :   }
    6589           6 : }
    6590             : 
    6591             : 
    6592         204 : static void GetXValue(Local<Name> name,
    6593             :                       const v8::PropertyCallbackInfo<v8::Value>& info) {
    6594         204 :   ApiTestFuzzer::Fuzz();
    6595         816 :   CHECK(info.Data()
    6596             :             ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
    6597             :             .FromJust());
    6598         816 :   CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
    6599             :             .FromJust());
    6600             :   info.GetReturnValue().Set(name);
    6601         204 : }
    6602             : 
    6603             : 
    6604       25881 : THREADED_TEST(SimplePropertyRead) {
    6605           6 :   LocalContext context;
    6606           6 :   v8::Isolate* isolate = context->GetIsolate();
    6607          12 :   v8::HandleScope scope(isolate);
    6608           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6609          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6610          36 :   CHECK(context->Global()
    6611             :             ->Set(context.local(), v8_str("obj"),
    6612             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6613             :             .FromJust());
    6614             :   Local<Script> script = v8_compile("obj.x");
    6615          66 :   for (int i = 0; i < 10; i++) {
    6616          60 :     Local<Value> result = script->Run(context.local()).ToLocalChecked();
    6617         180 :     CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
    6618           6 :   }
    6619           6 : }
    6620             : 
    6621             : 
    6622       25881 : THREADED_TEST(DefinePropertyOnAPIAccessor) {
    6623           6 :   LocalContext context;
    6624           6 :   v8::Isolate* isolate = context->GetIsolate();
    6625          12 :   v8::HandleScope scope(isolate);
    6626           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6627          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6628          36 :   CHECK(context->Global()
    6629             :             ->Set(context.local(), v8_str("obj"),
    6630             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6631             :             .FromJust());
    6632             : 
    6633             :   // Uses getOwnPropertyDescriptor to check the configurable status
    6634             :   Local<Script> script_desc = v8_compile(
    6635             :       "var prop = Object.getOwnPropertyDescriptor( "
    6636             :       "obj, 'x');"
    6637             :       "prop.configurable;");
    6638           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6639           6 :   CHECK(result->BooleanValue(isolate));
    6640             : 
    6641             :   // Redefine get - but still configurable
    6642             :   Local<Script> script_define = v8_compile(
    6643             :       "var desc = { get: function(){return 42; },"
    6644             :       "            configurable: true };"
    6645             :       "Object.defineProperty(obj, 'x', desc);"
    6646             :       "obj.x");
    6647           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6648          12 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6649             : 
    6650             :   // Check that the accessor is still configurable
    6651           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6652           6 :   CHECK(result->BooleanValue(isolate));
    6653             : 
    6654             :   // Redefine to a non-configurable
    6655             :   script_define = v8_compile(
    6656             :       "var desc = { get: function(){return 43; },"
    6657             :       "             configurable: false };"
    6658             :       "Object.defineProperty(obj, 'x', desc);"
    6659             :       "obj.x");
    6660           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6661          12 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6662           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6663           6 :   CHECK(!result->BooleanValue(isolate));
    6664             : 
    6665             :   // Make sure that it is not possible to redefine again
    6666          12 :   v8::TryCatch try_catch(isolate);
    6667          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6668           6 :   CHECK(try_catch.HasCaught());
    6669          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6670           6 :   CHECK_EQ(0,
    6671           6 :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6672           6 : }
    6673             : 
    6674             : 
    6675       25881 : THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
    6676           6 :   v8::Isolate* isolate = CcTest::isolate();
    6677           6 :   v8::HandleScope scope(isolate);
    6678           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6679          18 :   templ->SetAccessor(v8_str("x"), GetXValue, nullptr, v8_str("donut"));
    6680          12 :   LocalContext context;
    6681          36 :   CHECK(context->Global()
    6682             :             ->Set(context.local(), v8_str("obj"),
    6683             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6684             :             .FromJust());
    6685             : 
    6686             :   Local<Script> script_desc = v8_compile(
    6687             :       "var prop ="
    6688             :       "Object.getOwnPropertyDescriptor( "
    6689             :       "obj, 'x');"
    6690             :       "prop.configurable;");
    6691           6 :   Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
    6692           6 :   CHECK(result->BooleanValue(isolate));
    6693             : 
    6694             :   Local<Script> script_define = v8_compile(
    6695             :       "var desc = {get: function(){return 42; },"
    6696             :       "            configurable: true };"
    6697             :       "Object.defineProperty(obj, 'x', desc);"
    6698             :       "obj.x");
    6699           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6700          12 :   CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
    6701             : 
    6702           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6703           6 :   CHECK(result->BooleanValue(isolate));
    6704             : 
    6705             :   script_define = v8_compile(
    6706             :       "var desc = {get: function(){return 43; },"
    6707             :       "            configurable: false };"
    6708             :       "Object.defineProperty(obj, 'x', desc);"
    6709             :       "obj.x");
    6710           6 :   result = script_define->Run(context.local()).ToLocalChecked();
    6711          12 :   CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
    6712             : 
    6713           6 :   result = script_desc->Run(context.local()).ToLocalChecked();
    6714           6 :   CHECK(!result->BooleanValue(isolate));
    6715             : 
    6716          12 :   v8::TryCatch try_catch(isolate);
    6717          12 :   CHECK(script_define->Run(context.local()).IsEmpty());
    6718           6 :   CHECK(try_catch.HasCaught());
    6719          12 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    6720           6 :   CHECK_EQ(0,
    6721           6 :            strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6722           6 : }
    6723             : 
    6724             : 
    6725          72 : static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
    6726             :                                                char const* name) {
    6727             :   return v8::Local<v8::Object>::Cast(
    6728             :       (*context)
    6729             :           ->Global()
    6730         288 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
    6731         144 :           .ToLocalChecked());
    6732             : }
    6733             : 
    6734             : 
    6735       25881 : THREADED_TEST(DefineAPIAccessorOnObject) {
    6736           6 :   v8::Isolate* isolate = CcTest::isolate();
    6737           6 :   v8::HandleScope scope(isolate);
    6738           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6739          12 :   LocalContext context;
    6740             : 
    6741          42 :   CHECK(context->Global()
    6742             :             ->Set(context.local(), v8_str("obj1"),
    6743             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6744             :             .FromJust());
    6745             :   CompileRun("var obj2 = {};");
    6746             : 
    6747           6 :   CHECK(CompileRun("obj1.x")->IsUndefined());
    6748           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6749             : 
    6750          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6751             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6752             :                           v8_str("donut"))
    6753             :             .FromJust());
    6754             : 
    6755           6 :   ExpectString("obj1.x", "x");
    6756           6 :   CHECK(CompileRun("obj2.x")->IsUndefined());
    6757             : 
    6758          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6759             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6760             :                           v8_str("donut"))
    6761             :             .FromJust());
    6762             : 
    6763           6 :   ExpectString("obj1.x", "x");
    6764           6 :   ExpectString("obj2.x", "x");
    6765             : 
    6766             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6767             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6768             : 
    6769             :   CompileRun(
    6770             :       "Object.defineProperty(obj1, 'x',"
    6771             :       "{ get: function() { return 'y'; }, configurable: true })");
    6772             : 
    6773           6 :   ExpectString("obj1.x", "y");
    6774           6 :   ExpectString("obj2.x", "x");
    6775             : 
    6776             :   CompileRun(
    6777             :       "Object.defineProperty(obj2, 'x',"
    6778             :       "{ get: function() { return 'y'; }, configurable: true })");
    6779             : 
    6780           6 :   ExpectString("obj1.x", "y");
    6781           6 :   ExpectString("obj2.x", "y");
    6782             : 
    6783             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6784             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6785             : 
    6786          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6787             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6788             :                           v8_str("donut"))
    6789             :             .FromJust());
    6790          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6791             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6792             :                           v8_str("donut"))
    6793             :             .FromJust());
    6794             : 
    6795           6 :   ExpectString("obj1.x", "x");
    6796           6 :   ExpectString("obj2.x", "x");
    6797             : 
    6798             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6799             :   ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6800             : 
    6801             :   // Define getters/setters, but now make them not configurable.
    6802             :   CompileRun(
    6803             :       "Object.defineProperty(obj1, 'x',"
    6804             :       "{ get: function() { return 'z'; }, configurable: false })");
    6805             :   CompileRun(
    6806             :       "Object.defineProperty(obj2, 'x',"
    6807             :       "{ get: function() { return 'z'; }, configurable: false })");
    6808             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6809             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6810             : 
    6811           6 :   ExpectString("obj1.x", "z");
    6812           6 :   ExpectString("obj2.x", "z");
    6813             : 
    6814          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6815             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6816             :                            v8_str("donut"))
    6817             :              .FromJust());
    6818          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6819             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6820             :                            v8_str("donut"))
    6821             :              .FromJust());
    6822             : 
    6823           6 :   ExpectString("obj1.x", "z");
    6824          12 :   ExpectString("obj2.x", "z");
    6825           6 : }
    6826             : 
    6827             : 
    6828       25881 : THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
    6829           6 :   v8::Isolate* isolate = CcTest::isolate();
    6830           6 :   v8::HandleScope scope(isolate);
    6831           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6832          12 :   LocalContext context;
    6833             : 
    6834          42 :   CHECK(context->Global()
    6835             :             ->Set(context.local(), v8_str("obj1"),
    6836             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6837             :             .FromJust());
    6838             :   CompileRun("var obj2 = {};");
    6839             : 
    6840          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6841             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6842             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6843             :             .FromJust());
    6844          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6845             :             ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6846             :                           v8_str("donut"), v8::DEFAULT, v8::DontDelete)
    6847             :             .FromJust());
    6848             : 
    6849           6 :   ExpectString("obj1.x", "x");
    6850           6 :   ExpectString("obj2.x", "x");
    6851             : 
    6852             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
    6853             :   ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
    6854             : 
    6855          30 :   CHECK(!GetGlobalProperty(&context, "obj1")
    6856             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6857             :                            v8_str("donut"))
    6858             :              .FromJust());
    6859          30 :   CHECK(!GetGlobalProperty(&context, "obj2")
    6860             :              ->SetAccessor(context.local(), v8_str("x"), GetXValue, nullptr,
    6861             :                            v8_str("donut"))
    6862             :              .FromJust());
    6863             : 
    6864             :   {
    6865           6 :     v8::TryCatch try_catch(isolate);
    6866             :     CompileRun(
    6867             :         "Object.defineProperty(obj1, 'x',"
    6868             :         "{get: function() { return 'func'; }})");
    6869           6 :     CHECK(try_catch.HasCaught());
    6870          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6871           6 :     CHECK_EQ(
    6872           6 :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6873             :   }
    6874             :   {
    6875           6 :     v8::TryCatch try_catch(isolate);
    6876             :     CompileRun(
    6877             :         "Object.defineProperty(obj2, 'x',"
    6878             :         "{get: function() { return 'func'; }})");
    6879           6 :     CHECK(try_catch.HasCaught());
    6880          12 :     String::Utf8Value exception_value(isolate, try_catch.Exception());
    6881           6 :     CHECK_EQ(
    6882           6 :         0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
    6883           6 :   }
    6884           6 : }
    6885             : 
    6886             : 
    6887          24 : static void Get239Value(Local<Name> name,
    6888             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
    6889          24 :   ApiTestFuzzer::Fuzz();
    6890          96 :   CHECK(info.Data()
    6891             :             ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
    6892             :             .FromJust());
    6893          96 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
    6894             :             .FromJust());
    6895             :   info.GetReturnValue().Set(name);
    6896          24 : }
    6897             : 
    6898             : 
    6899       25881 : THREADED_TEST(ElementAPIAccessor) {
    6900           6 :   v8::Isolate* isolate = CcTest::isolate();
    6901           6 :   v8::HandleScope scope(isolate);
    6902           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6903          12 :   LocalContext context;
    6904             : 
    6905          42 :   CHECK(context->Global()
    6906             :             ->Set(context.local(), v8_str("obj1"),
    6907             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6908             :             .FromJust());
    6909             :   CompileRun("var obj2 = {};");
    6910             : 
    6911          30 :   CHECK(GetGlobalProperty(&context, "obj1")
    6912             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6913             :                           v8_str("donut"))
    6914             :             .FromJust());
    6915          30 :   CHECK(GetGlobalProperty(&context, "obj2")
    6916             :             ->SetAccessor(context.local(), v8_str("239"), Get239Value, nullptr,
    6917             :                           v8_str("donut"))
    6918             :             .FromJust());
    6919             : 
    6920           6 :   ExpectString("obj1[239]", "239");
    6921           6 :   ExpectString("obj2[239]", "239");
    6922           6 :   ExpectString("obj1['239']", "239");
    6923          12 :   ExpectString("obj2['239']", "239");
    6924           6 : }
    6925             : 
    6926             : 
    6927       25875 : v8::Persistent<Value> xValue;
    6928             : 
    6929             : 
    6930         120 : static void SetXValue(Local<Name> name, Local<Value> value,
    6931             :                       const v8::PropertyCallbackInfo<void>& info) {
    6932         120 :   Local<Context> context = info.GetIsolate()->GetCurrentContext();
    6933         240 :   CHECK(value->Equals(context, v8_num(4)).FromJust());
    6934         360 :   CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
    6935         360 :   CHECK(name->Equals(context, v8_str("x")).FromJust());
    6936         120 :   CHECK(xValue.IsEmpty());
    6937             :   xValue.Reset(info.GetIsolate(), value);
    6938         120 : }
    6939             : 
    6940             : 
    6941       25881 : THREADED_TEST(SimplePropertyWrite) {
    6942           6 :   v8::Isolate* isolate = CcTest::isolate();
    6943           6 :   v8::HandleScope scope(isolate);
    6944           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6945          18 :   templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
    6946          12 :   LocalContext context;
    6947          36 :   CHECK(context->Global()
    6948             :             ->Set(context.local(), v8_str("obj"),
    6949             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6950             :             .FromJust());
    6951             :   Local<Script> script = v8_compile("obj.x = 4");
    6952          66 :   for (int i = 0; i < 10; i++) {
    6953          60 :     CHECK(xValue.IsEmpty());
    6954          60 :     script->Run(context.local()).ToLocalChecked();
    6955         240 :     CHECK(v8_num(4)
    6956             :               ->Equals(context.local(),
    6957             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6958             :               .FromJust());
    6959             :     xValue.Reset();
    6960           6 :   }
    6961           6 : }
    6962             : 
    6963             : 
    6964       25881 : THREADED_TEST(SetterOnly) {
    6965           6 :   v8::Isolate* isolate = CcTest::isolate();
    6966           6 :   v8::HandleScope scope(isolate);
    6967           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6968          18 :   templ->SetAccessor(v8_str("x"), nullptr, SetXValue, v8_str("donut"));
    6969          12 :   LocalContext context;
    6970          36 :   CHECK(context->Global()
    6971             :             ->Set(context.local(), v8_str("obj"),
    6972             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6973             :             .FromJust());
    6974             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    6975          66 :   for (int i = 0; i < 10; i++) {
    6976          60 :     CHECK(xValue.IsEmpty());
    6977          60 :     script->Run(context.local()).ToLocalChecked();
    6978         240 :     CHECK(v8_num(4)
    6979             :               ->Equals(context.local(),
    6980             :                        Local<Value>::New(CcTest::isolate(), xValue))
    6981             :               .FromJust());
    6982             :     xValue.Reset();
    6983           6 :   }
    6984           6 : }
    6985             : 
    6986             : 
    6987       25881 : THREADED_TEST(NoAccessors) {
    6988           6 :   v8::Isolate* isolate = CcTest::isolate();
    6989           6 :   v8::HandleScope scope(isolate);
    6990           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    6991             :   templ->SetAccessor(v8_str("x"),
    6992             :                      static_cast<v8::AccessorGetterCallback>(nullptr), nullptr,
    6993          12 :                      v8_str("donut"));
    6994          12 :   LocalContext context;
    6995          36 :   CHECK(context->Global()
    6996             :             ->Set(context.local(), v8_str("obj"),
    6997             :                   templ->NewInstance(context.local()).ToLocalChecked())
    6998             :             .FromJust());
    6999             :   Local<Script> script = v8_compile("obj.x = 4; obj.x");
    7000          66 :   for (int i = 0; i < 10; i++) {
    7001          60 :     script->Run(context.local()).ToLocalChecked();
    7002           6 :   }
    7003           6 : }
    7004             : 
    7005             : 
    7006       25881 : THREADED_TEST(MultiContexts) {
    7007           6 :   v8::Isolate* isolate = CcTest::isolate();
    7008           6 :   v8::HandleScope scope(isolate);
    7009           6 :   v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7010             :   templ->Set(v8_str("dummy"),
    7011          18 :              v8::FunctionTemplate::New(isolate, DummyCallHandler));
    7012             : 
    7013           6 :   Local<String> password = v8_str("Password");
    7014             : 
    7015             :   // Create an environment
    7016          12 :   LocalContext context0(nullptr, templ);
    7017           6 :   context0->SetSecurityToken(password);
    7018           6 :   v8::Local<v8::Object> global0 = context0->Global();
    7019          18 :   CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
    7020             :             .FromJust());
    7021          24 :   CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
    7022             :                      .ToLocalChecked()
    7023             :                      ->Int32Value(context0.local())
    7024             :                      .FromJust());
    7025             : 
    7026             :   // Create an independent environment
    7027          12 :   LocalContext context1(nullptr, templ);
    7028           6 :   context1->SetSecurityToken(password);
    7029           6 :   v8::Local<v8::Object> global1 = context1->Global();
    7030          18 :   CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
    7031             :             .FromJust());
    7032          12 :   CHECK(!global0->Equals(context1.local(), global1).FromJust());
    7033          24 :   CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
    7034             :                      .ToLocalChecked()
    7035             :                      ->Int32Value(context0.local())
    7036             :                      .FromJust());
    7037          24 :   CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
    7038             :                      .ToLocalChecked()
    7039             :                      ->Int32Value(context1.local())
    7040             :                      .FromJust());
    7041             : 
    7042             :   // Now create a new context with the old global
    7043          12 :   LocalContext context2(nullptr, templ, global1);
    7044           6 :   context2->SetSecurityToken(password);
    7045           6 :   v8::Local<v8::Object> global2 = context2->Global();
    7046          12 :   CHECK(global1->Equals(context2.local(), global2).FromJust());
    7047          24 :   CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
    7048             :                   .ToLocalChecked()
    7049             :                   ->Int32Value(context1.local())
    7050             :                   .FromJust());
    7051          24 :   CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
    7052             :                   .ToLocalChecked()
    7053             :                   ->Int32Value(context2.local())
    7054           6 :                   .FromJust());
    7055           6 : }
    7056             : 
    7057             : 
    7058       25881 : THREADED_TEST(FunctionPrototypeAcrossContexts) {
    7059             :   // Make sure that functions created by cloning boilerplates cannot
    7060             :   // communicate through their __proto__ field.
    7061             : 
    7062           6 :   v8::HandleScope scope(CcTest::isolate());
    7063             : 
    7064          12 :   LocalContext env0;
    7065           6 :   v8::Local<v8::Object> global0 = env0->Global();
    7066          18 :   v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
    7067           6 :                                       .ToLocalChecked()
    7068             :                                       .As<v8::Object>();
    7069             :   v8::Local<v8::Object> tostring0 =
    7070          18 :       object0->Get(env0.local(), v8_str("toString"))
    7071           6 :           .ToLocalChecked()
    7072             :           .As<v8::Object>();
    7073             :   v8::Local<v8::Object> proto0 =
    7074          18 :       tostring0->Get(env0.local(), v8_str("__proto__"))
    7075           6 :           .ToLocalChecked()
    7076             :           .As<v8::Object>();
    7077          18 :   CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
    7078             : 
    7079          12 :   LocalContext env1;
    7080           6 :   v8::Local<v8::Object> global1 = env1->Global();
    7081          18 :   v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
    7082           6 :                                       .ToLocalChecked()
    7083             :                                       .As<v8::Object>();
    7084             :   v8::Local<v8::Object> tostring1 =
    7085          18 :       object1->Get(env1.local(), v8_str("toString"))
    7086           6 :           .ToLocalChecked()
    7087             :           .As<v8::Object>();
    7088             :   v8::Local<v8::Object> proto1 =
    7089          18 :       tostring1->Get(env1.local(), v8_str("__proto__"))
    7090           6 :           .ToLocalChecked()
    7091             :           .As<v8::Object>();
    7092          24 :   CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
    7093           6 : }
    7094             : 
    7095             : 
    7096       25881 : THREADED_TEST(Regress892105) {
    7097             :   // Make sure that object and array literals created by cloning
    7098             :   // boilerplates cannot communicate through their __proto__
    7099             :   // field. This is rather difficult to check, but we try to add stuff
    7100             :   // to Object.prototype and Array.prototype and create a new
    7101             :   // environment. This should succeed.
    7102             : 
    7103           6 :   v8::HandleScope scope(CcTest::isolate());
    7104             : 
    7105             :   Local<String> source = v8_str(
    7106             :       "Object.prototype.obj = 1234;"
    7107             :       "Array.prototype.arr = 4567;"
    7108           6 :       "8901");
    7109             : 
    7110          12 :   LocalContext env0;
    7111           6 :   Local<Script> script0 = v8_compile(source);
    7112          24 :   CHECK_EQ(8901.0, script0->Run(env0.local())
    7113             :                        .ToLocalChecked()
    7114             :                        ->NumberValue(env0.local())
    7115             :                        .FromJust());
    7116             : 
    7117          12 :   LocalContext env1;
    7118           6 :   Local<Script> script1 = v8_compile(source);
    7119          24 :   CHECK_EQ(8901.0, script1->Run(env1.local())
    7120             :                        .ToLocalChecked()
    7121             :                        ->NumberValue(env1.local())
    7122           6 :                        .FromJust());
    7123           6 : }
    7124             : 
    7125          60 : static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7126             :   args.GetReturnValue().Set(args.This());
    7127          30 : }
    7128             : 
    7129       25881 : THREADED_TEST(UndetectableObject) {
    7130           6 :   LocalContext env;
    7131          12 :   v8::HandleScope scope(env->GetIsolate());
    7132             : 
    7133             :   Local<v8::FunctionTemplate> desc =
    7134           6 :       v8::FunctionTemplate::New(env->GetIsolate());
    7135          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7136          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7137             : 
    7138           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7139           6 :                               .ToLocalChecked()
    7140           6 :                               ->NewInstance(env.local())
    7141             :                               .ToLocalChecked();
    7142          30 :   CHECK(
    7143             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7144             : 
    7145           6 :   ExpectString("undetectable.toString()", "[object Object]");
    7146           6 :   ExpectString("typeof undetectable", "undefined");
    7147           6 :   ExpectString("typeof(undetectable)", "undefined");
    7148           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
    7149           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
    7150           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
    7151           6 :   ExpectBoolean("!undetectable", true);
    7152             : 
    7153           6 :   ExpectObject("true&&undetectable", obj);
    7154           6 :   ExpectBoolean("false&&undetectable", false);
    7155           6 :   ExpectBoolean("true||undetectable", true);
    7156           6 :   ExpectObject("false||undetectable", obj);
    7157             : 
    7158           6 :   ExpectObject("undetectable&&true", obj);
    7159           6 :   ExpectObject("undetectable&&false", obj);
    7160           6 :   ExpectBoolean("undetectable||true", true);
    7161           6 :   ExpectBoolean("undetectable||false", false);
    7162             : 
    7163           6 :   ExpectBoolean("undetectable==null", true);
    7164           6 :   ExpectBoolean("null==undetectable", true);
    7165           6 :   ExpectBoolean("undetectable==undefined", true);
    7166           6 :   ExpectBoolean("undefined==undetectable", true);
    7167           6 :   ExpectBoolean("undetectable==undetectable", true);
    7168             : 
    7169             : 
    7170           6 :   ExpectBoolean("undetectable===null", false);
    7171           6 :   ExpectBoolean("null===undetectable", false);
    7172           6 :   ExpectBoolean("undetectable===undefined", false);
    7173           6 :   ExpectBoolean("undefined===undetectable", false);
    7174          12 :   ExpectBoolean("undetectable===undetectable", true);
    7175           6 : }
    7176             : 
    7177             : 
    7178       25881 : THREADED_TEST(VoidLiteral) {
    7179           6 :   LocalContext env;
    7180           6 :   v8::Isolate* isolate = env->GetIsolate();
    7181          12 :   v8::HandleScope scope(isolate);
    7182             : 
    7183           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7184          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7185          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7186             : 
    7187           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7188           6 :                               .ToLocalChecked()
    7189           6 :                               ->NewInstance(env.local())
    7190             :                               .ToLocalChecked();
    7191          30 :   CHECK(
    7192             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7193             : 
    7194           6 :   ExpectBoolean("undefined == void 0", true);
    7195           6 :   ExpectBoolean("undetectable == void 0", true);
    7196           6 :   ExpectBoolean("null == void 0", true);
    7197           6 :   ExpectBoolean("undefined === void 0", true);
    7198           6 :   ExpectBoolean("undetectable === void 0", false);
    7199           6 :   ExpectBoolean("null === void 0", false);
    7200             : 
    7201           6 :   ExpectBoolean("void 0 == undefined", true);
    7202           6 :   ExpectBoolean("void 0 == undetectable", true);
    7203           6 :   ExpectBoolean("void 0 == null", true);
    7204           6 :   ExpectBoolean("void 0 === undefined", true);
    7205           6 :   ExpectBoolean("void 0 === undetectable", false);
    7206           6 :   ExpectBoolean("void 0 === null", false);
    7207             : 
    7208             :   ExpectString(
    7209             :       "(function() {"
    7210             :       "  try {"
    7211             :       "    return x === void 0;"
    7212             :       "  } catch(e) {"
    7213             :       "    return e.toString();"
    7214             :       "  }"
    7215             :       "})()",
    7216           6 :       "ReferenceError: x is not defined");
    7217             :   ExpectString(
    7218             :       "(function() {"
    7219             :       "  try {"
    7220             :       "    return void 0 === x;"
    7221             :       "  } catch(e) {"
    7222             :       "    return e.toString();"
    7223             :       "  }"
    7224             :       "})()",
    7225          12 :       "ReferenceError: x is not defined");
    7226           6 : }
    7227             : 
    7228             : 
    7229       25881 : THREADED_TEST(ExtensibleOnUndetectable) {
    7230           6 :   LocalContext env;
    7231           6 :   v8::Isolate* isolate = env->GetIsolate();
    7232          12 :   v8::HandleScope scope(isolate);
    7233             : 
    7234           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7235          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7236          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7237             : 
    7238           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7239           6 :                               .ToLocalChecked()
    7240           6 :                               ->NewInstance(env.local())
    7241             :                               .ToLocalChecked();
    7242          30 :   CHECK(
    7243             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7244             : 
    7245             :   Local<String> source = v8_str(
    7246             :       "undetectable.x = 42;"
    7247           6 :       "undetectable.x");
    7248             : 
    7249           6 :   Local<Script> script = v8_compile(source);
    7250             : 
    7251          24 :   CHECK(v8::Integer::New(isolate, 42)
    7252             :             ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
    7253             :             .FromJust());
    7254             : 
    7255           6 :   ExpectBoolean("Object.isExtensible(undetectable)", true);
    7256             : 
    7257           6 :   source = v8_str("Object.preventExtensions(undetectable);");
    7258           6 :   script = v8_compile(source);
    7259           6 :   script->Run(env.local()).ToLocalChecked();
    7260           6 :   ExpectBoolean("Object.isExtensible(undetectable)", false);
    7261             : 
    7262           6 :   source = v8_str("undetectable.y = 2000;");
    7263           6 :   script = v8_compile(source);
    7264           6 :   script->Run(env.local()).ToLocalChecked();
    7265          12 :   ExpectBoolean("undetectable.y == undefined", true);
    7266           6 : }
    7267             : 
    7268       25881 : THREADED_TEST(ConstructCallWithUndetectable) {
    7269           6 :   LocalContext env;
    7270           6 :   v8::Isolate* isolate = env->GetIsolate();
    7271          12 :   v8::HandleScope scope(isolate);
    7272             : 
    7273           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7274          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
    7275          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
    7276             : 
    7277           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7278           6 :                               .ToLocalChecked()
    7279           6 :                               ->NewInstance(env.local())
    7280             :                               .ToLocalChecked();
    7281          30 :   CHECK(
    7282             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
    7283             : 
    7284             :   // Undetectable object cannot be called as constructor.
    7285          12 :   v8::TryCatch try_catch(env->GetIsolate());
    7286           6 :   CHECK(CompileRun("new undetectable()").IsEmpty());
    7287           6 :   CHECK(try_catch.HasCaught());
    7288          18 :   String::Utf8Value exception_value(env->GetIsolate(), try_catch.Exception());
    7289           6 :   CHECK_EQ(0, strcmp("TypeError: undetectable is not a constructor",
    7290           6 :                      *exception_value));
    7291           6 : }
    7292             : 
    7293             : static int increment_callback_counter = 0;
    7294             : 
    7295          12 : static void IncrementCounterConstructCallback(
    7296          36 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7297          12 :   increment_callback_counter++;
    7298          48 :   CHECK(Local<Object>::Cast(args.NewTarget())
    7299             :             ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("counter"),
    7300             :                   v8_num(increment_callback_counter))
    7301             :             .FromJust());
    7302             :   args.GetReturnValue().Set(args.NewTarget());
    7303          12 : }
    7304             : 
    7305       25881 : THREADED_TEST(SetCallAsFunctionHandlerConstructor) {
    7306           6 :   LocalContext env;
    7307           6 :   v8::Isolate* isolate = env->GetIsolate();
    7308          12 :   v8::HandleScope scope(isolate);
    7309             : 
    7310           6 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
    7311             :   desc->InstanceTemplate()->SetCallAsFunctionHandler(
    7312          12 :       IncrementCounterConstructCallback);  // callable
    7313             : 
    7314           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
    7315           6 :                               .ToLocalChecked()
    7316           6 :                               ->NewInstance(env.local())
    7317             :                               .ToLocalChecked();
    7318          30 :   CHECK(env->Global()->Set(env.local(), v8_str("Counter"), obj).FromJust());
    7319             : 
    7320           6 :   ExpectInt32("(new Counter()).counter", 1);
    7321           6 :   CHECK_EQ(1, increment_callback_counter);
    7322           6 :   ExpectInt32("(new Counter()).counter", 2);
    7323          12 :   CHECK_EQ(2, increment_callback_counter);
    7324           6 : }
    7325             : // The point of this test is type checking. We run it only so compilers
    7326             : // don't complain about an unused function.
    7327       25880 : TEST(PersistentHandles) {
    7328           5 :   LocalContext env;
    7329           5 :   v8::Isolate* isolate = CcTest::isolate();
    7330          10 :   v8::HandleScope scope(isolate);
    7331           5 :   Local<String> str = v8_str("foo");
    7332             :   v8::Persistent<String> p_str(isolate, str);
    7333             :   p_str.Reset();
    7334             :   Local<Script> scr = v8_compile("");
    7335             :   v8::Persistent<Script> p_scr(isolate, scr);
    7336             :   p_scr.Reset();
    7337           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    7338             :   v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
    7339           5 :   p_templ.Reset();
    7340           5 : }
    7341             : 
    7342             : 
    7343           6 : static void HandleLogDelegator(
    7344             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    7345           6 :   ApiTestFuzzer::Fuzz();
    7346           6 : }
    7347             : 
    7348             : 
    7349       25881 : THREADED_TEST(GlobalObjectTemplate) {
    7350           6 :   v8::Isolate* isolate = CcTest::isolate();
    7351           6 :   v8::HandleScope handle_scope(isolate);
    7352           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
    7353             :   global_template->Set(v8_str("JSNI_Log"),
    7354          18 :                        v8::FunctionTemplate::New(isolate, HandleLogDelegator));
    7355           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
    7356             :   Context::Scope context_scope(context);
    7357           6 :   CompileRun("JSNI_Log('LOG')");
    7358           6 : }
    7359             : 
    7360             : 
    7361             : static const char* kSimpleExtensionSource =
    7362             :     "function Foo() {"
    7363             :     "  return 4;"
    7364             :     "}";
    7365             : 
    7366             : 
    7367       25880 : TEST(SimpleExtensions) {
    7368           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7369             :   v8::RegisterExtension(
    7370          10 :       v8::base::make_unique<Extension>("simpletest", kSimpleExtensionSource));
    7371           5 :   const char* extension_names[] = {"simpletest"};
    7372             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7373           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7374             :   Context::Scope lock(context);
    7375             :   v8::Local<Value> result = CompileRun("Foo()");
    7376          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7377           5 :             .FromJust());
    7378           5 : }
    7379             : 
    7380             : 
    7381             : static const char* kStackTraceFromExtensionSource =
    7382             :     "function foo() {"
    7383             :     "  throw new Error();"
    7384             :     "}"
    7385             :     "function bar() {"
    7386             :     "  foo();"
    7387             :     "}";
    7388             : 
    7389             : 
    7390       25880 : TEST(StackTraceInExtension) {
    7391           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7392             :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7393          10 :       "stacktracetest", kStackTraceFromExtensionSource));
    7394           5 :   const char* extension_names[] = {"stacktracetest"};
    7395             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7396           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7397             :   Context::Scope lock(context);
    7398             :   CompileRun(
    7399             :       "function user() { bar(); }"
    7400             :       "var error;"
    7401             :       "try{ user(); } catch (e) { error = e; }");
    7402           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
    7403           5 :   CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
    7404          10 :   CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
    7405           5 : }
    7406             : 
    7407             : 
    7408       25880 : TEST(NullExtensions) {
    7409           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7410          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>("nulltest", nullptr));
    7411           5 :   const char* extension_names[] = {"nulltest"};
    7412             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7413           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7414             :   Context::Scope lock(context);
    7415             :   v8::Local<Value> result = CompileRun("1+3");
    7416          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7417           5 :             .FromJust());
    7418           5 : }
    7419             : 
    7420             : static const char* kEmbeddedExtensionSource =
    7421             :     "function Ret54321(){return 54321;}~~@@$"
    7422             :     "$%% THIS IS A SERIES OF NON-nullptr-TERMINATED STRINGS.";
    7423             : static const int kEmbeddedExtensionSourceValidLen = 34;
    7424             : 
    7425             : 
    7426       25880 : TEST(ExtensionMissingSourceLength) {
    7427           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7428             :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7429          10 :       "srclentest_fail", kEmbeddedExtensionSource));
    7430           5 :   const char* extension_names[] = {"srclentest_fail"};
    7431             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7432           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7433           5 :   CHECK_NULL(*context);
    7434           5 : }
    7435             : 
    7436             : 
    7437       25880 : TEST(ExtensionWithSourceLength) {
    7438          40 :   for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
    7439          20 :        source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
    7440          15 :     v8::HandleScope handle_scope(CcTest::isolate());
    7441             :     i::ScopedVector<char> extension_name(32);
    7442          15 :     i::SNPrintF(extension_name, "ext #%d", source_len);
    7443             :     v8::RegisterExtension(v8::base::make_unique<Extension>(
    7444             :         extension_name.start(), kEmbeddedExtensionSource, 0, nullptr,
    7445          30 :         source_len));
    7446          15 :     const char* extension_names[1] = {extension_name.start()};
    7447             :     v8::ExtensionConfiguration extensions(1, extension_names);
    7448          15 :     v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7449          15 :     if (source_len == kEmbeddedExtensionSourceValidLen) {
    7450             :       Context::Scope lock(context);
    7451           5 :       v8::Local<Value> result = CompileRun("Ret54321()");
    7452          15 :       CHECK(v8::Integer::New(CcTest::isolate(), 54321)
    7453             :                 ->Equals(context, result)
    7454             :                 .FromJust());
    7455             :     } else {
    7456             :       // Anything but exactly the right length should fail to compile.
    7457          10 :       CHECK_NULL(*context);
    7458             :     }
    7459          15 :   }
    7460           5 : }
    7461             : 
    7462             : 
    7463             : static const char* kEvalExtensionSource1 =
    7464             :     "function UseEval1() {"
    7465             :     "  var x = 42;"
    7466             :     "  return eval('x');"
    7467             :     "}";
    7468             : 
    7469             : 
    7470             : static const char* kEvalExtensionSource2 =
    7471             :     "(function() {"
    7472             :     "  var x = 42;"
    7473             :     "  function e() {"
    7474             :     "    return eval('x');"
    7475             :     "  }"
    7476             :     "  this.UseEval2 = e;"
    7477             :     "})()";
    7478             : 
    7479             : 
    7480       25880 : TEST(UseEvalFromExtension) {
    7481           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7482             :   v8::RegisterExtension(
    7483          10 :       v8::base::make_unique<Extension>("evaltest1", kEvalExtensionSource1));
    7484             :   v8::RegisterExtension(
    7485          10 :       v8::base::make_unique<Extension>("evaltest2", kEvalExtensionSource2));
    7486           5 :   const char* extension_names[] = {"evaltest1", "evaltest2"};
    7487             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7488           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7489             :   Context::Scope lock(context);
    7490             :   v8::Local<Value> result = CompileRun("UseEval1()");
    7491          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7492             :             .FromJust());
    7493             :   result = CompileRun("UseEval2()");
    7494          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7495           5 :             .FromJust());
    7496           5 : }
    7497             : 
    7498             : 
    7499             : static const char* kWithExtensionSource1 =
    7500             :     "function UseWith1() {"
    7501             :     "  var x = 42;"
    7502             :     "  with({x:87}) { return x; }"
    7503             :     "}";
    7504             : 
    7505             : 
    7506             : static const char* kWithExtensionSource2 =
    7507             :     "(function() {"
    7508             :     "  var x = 42;"
    7509             :     "  function e() {"
    7510             :     "    with ({x:87}) { return x; }"
    7511             :     "  }"
    7512             :     "  this.UseWith2 = e;"
    7513             :     "})()";
    7514             : 
    7515             : 
    7516       25880 : TEST(UseWithFromExtension) {
    7517           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7518             :   v8::RegisterExtension(
    7519          10 :       v8::base::make_unique<Extension>("withtest1", kWithExtensionSource1));
    7520             :   v8::RegisterExtension(
    7521          10 :       v8::base::make_unique<Extension>("withtest2", kWithExtensionSource2));
    7522           5 :   const char* extension_names[] = {"withtest1", "withtest2"};
    7523             :   v8::ExtensionConfiguration extensions(2, extension_names);
    7524           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7525             :   Context::Scope lock(context);
    7526             :   v8::Local<Value> result = CompileRun("UseWith1()");
    7527          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7528             :             .FromJust());
    7529             :   result = CompileRun("UseWith2()");
    7530          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
    7531           5 :             .FromJust());
    7532           5 : }
    7533             : 
    7534             : 
    7535       25880 : TEST(AutoExtensions) {
    7536           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7537             :   auto extension =
    7538           5 :       v8::base::make_unique<Extension>("autotest", kSimpleExtensionSource);
    7539             :   extension->set_auto_enable(true);
    7540          10 :   v8::RegisterExtension(std::move(extension));
    7541           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
    7542             :   Context::Scope lock(context);
    7543             :   v8::Local<Value> result = CompileRun("Foo()");
    7544          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
    7545           5 :             .FromJust());
    7546           5 : }
    7547             : 
    7548             : 
    7549             : static const char* kSyntaxErrorInExtensionSource = "[";
    7550             : 
    7551             : 
    7552             : // Test that a syntax error in an extension does not cause a fatal
    7553             : // error but results in an empty context.
    7554       25880 : TEST(SyntaxErrorExtensions) {
    7555           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7556             :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7557          10 :       "syntaxerror", kSyntaxErrorInExtensionSource));
    7558           5 :   const char* extension_names[] = {"syntaxerror"};
    7559             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7560           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7561           5 :   CHECK(context.IsEmpty());
    7562           5 : }
    7563             : 
    7564             : 
    7565             : static const char* kExceptionInExtensionSource = "throw 42";
    7566             : 
    7567             : 
    7568             : // Test that an exception when installing an extension does not cause
    7569             : // a fatal error but results in an empty context.
    7570       25880 : TEST(ExceptionExtensions) {
    7571           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7572             :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7573          10 :       "exception", kExceptionInExtensionSource));
    7574           5 :   const char* extension_names[] = {"exception"};
    7575             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7576           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7577           5 :   CHECK(context.IsEmpty());
    7578           5 : }
    7579             : 
    7580             : static const char* kNativeCallInExtensionSource =
    7581             :     "function call_runtime_last_index_of(x) {"
    7582             :     "  return %StringLastIndexOf(x, 'bob');"
    7583             :     "}";
    7584             : 
    7585             : static const char* kNativeCallTest =
    7586             :     "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
    7587             : 
    7588             : // Test that a native runtime calls are supported in extensions.
    7589       25880 : TEST(NativeCallInExtensions) {
    7590           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7591             :   v8::RegisterExtension(v8::base::make_unique<Extension>(
    7592          10 :       "nativecall", kNativeCallInExtensionSource));
    7593           5 :   const char* extension_names[] = {"nativecall"};
    7594             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7595           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7596             :   Context::Scope lock(context);
    7597           5 :   v8::Local<Value> result = CompileRun(kNativeCallTest);
    7598          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 24))
    7599           5 :             .FromJust());
    7600           5 : }
    7601             : 
    7602             : 
    7603          30 : class NativeFunctionExtension : public Extension {
    7604             :  public:
    7605             :   NativeFunctionExtension(const char* name, const char* source,
    7606             :                           v8::FunctionCallback fun = &Echo)
    7607          15 :       : Extension(name, source), function_(fun) {}
    7608             : 
    7609           5 :   v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7610             :       v8::Isolate* isolate, v8::Local<v8::String> name) override {
    7611           5 :     return v8::FunctionTemplate::New(isolate, function_);
    7612             :   }
    7613             : 
    7614          10 :   static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7615           5 :     if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
    7616           5 :   }
    7617             : 
    7618             :  private:
    7619             :   v8::FunctionCallback function_;
    7620             : };
    7621             : 
    7622             : 
    7623       25880 : TEST(NativeFunctionDeclaration) {
    7624           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7625           5 :   const char* name = "nativedecl";
    7626             :   v8::RegisterExtension(v8::base::make_unique<NativeFunctionExtension>(
    7627          20 :       name, "native function foo();"));
    7628           5 :   const char* extension_names[] = {name};
    7629             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7630           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7631             :   Context::Scope lock(context);
    7632             :   v8::Local<Value> result = CompileRun("foo(42);");
    7633          15 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
    7634           5 :             .FromJust());
    7635           5 : }
    7636             : 
    7637             : 
    7638       25880 : TEST(NativeFunctionDeclarationError) {
    7639           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7640           5 :   const char* name = "nativedeclerr";
    7641             :   // Syntax error in extension code.
    7642             :   v8::RegisterExtension(v8::base::make_unique<NativeFunctionExtension>(
    7643          20 :       name, "native\nfunction foo();"));
    7644           5 :   const char* extension_names[] = {name};
    7645             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7646           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7647           5 :   CHECK(context.IsEmpty());
    7648           5 : }
    7649             : 
    7650             : 
    7651       25880 : TEST(NativeFunctionDeclarationErrorEscape) {
    7652           5 :   v8::HandleScope handle_scope(CcTest::isolate());
    7653           5 :   const char* name = "nativedeclerresc";
    7654             :   // Syntax error in extension code - escape code in "native" means that
    7655             :   // it's not treated as a keyword.
    7656             :   v8::RegisterExtension(v8::base::make_unique<NativeFunctionExtension>(
    7657          20 :       name, "nativ\\u0065 function foo();"));
    7658           5 :   const char* extension_names[] = {name};
    7659             :   v8::ExtensionConfiguration extensions(1, extension_names);
    7660           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
    7661           5 :   CHECK(context.IsEmpty());
    7662           5 : }
    7663             : 
    7664             : 
    7665          30 : static void CheckDependencies(const char* name, const char* expected) {
    7666          30 :   v8::HandleScope handle_scope(CcTest::isolate());
    7667             :   v8::ExtensionConfiguration config(1, &name);
    7668          60 :   LocalContext context(&config);
    7669         210 :   CHECK(
    7670             :       v8_str(expected)
    7671             :           ->Equals(context.local(), context->Global()
    7672             :                                         ->Get(context.local(), v8_str("loaded"))
    7673             :                                         .ToLocalChecked())
    7674          30 :           .FromJust());
    7675          30 : }
    7676             : 
    7677             : 
    7678             : /*
    7679             :  * Configuration:
    7680             :  *
    7681             :  *     /-- B <--\
    7682             :  * A <-          -- D <-- E
    7683             :  *     \-- C <--/
    7684             :  */
    7685       25881 : THREADED_TEST(ExtensionDependency) {
    7686             :   static const char* kEDeps[] = {"D"};
    7687             :   v8::RegisterExtension(
    7688          12 :       v8::base::make_unique<Extension>("E", "this.loaded += 'E';", 1, kEDeps));
    7689             :   static const char* kDDeps[] = {"B", "C"};
    7690             :   v8::RegisterExtension(
    7691          12 :       v8::base::make_unique<Extension>("D", "this.loaded += 'D';", 2, kDDeps));
    7692             :   static const char* kBCDeps[] = {"A"};
    7693             :   v8::RegisterExtension(
    7694          12 :       v8::base::make_unique<Extension>("B", "this.loaded += 'B';", 1, kBCDeps));
    7695             :   v8::RegisterExtension(
    7696          12 :       v8::base::make_unique<Extension>("C", "this.loaded += 'C';", 1, kBCDeps));
    7697             :   v8::RegisterExtension(
    7698          12 :       v8::base::make_unique<Extension>("A", "this.loaded += 'A';"));
    7699           6 :   CheckDependencies("A", "undefinedA");
    7700           6 :   CheckDependencies("B", "undefinedAB");
    7701           6 :   CheckDependencies("C", "undefinedAC");
    7702           6 :   CheckDependencies("D", "undefinedABCD");
    7703           6 :   CheckDependencies("E", "undefinedABCDE");
    7704           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7705             :   static const char* exts[2] = {"C", "E"};
    7706             :   v8::ExtensionConfiguration config(2, exts);
    7707          12 :   LocalContext context(&config);
    7708          42 :   CHECK(
    7709             :       v8_str("undefinedACBDE")
    7710             :           ->Equals(context.local(), context->Global()
    7711             :                                         ->Get(context.local(), v8_str("loaded"))
    7712             :                                         .ToLocalChecked())
    7713           6 :           .FromJust());
    7714           6 : }
    7715             : 
    7716             : 
    7717             : static const char* kExtensionTestScript =
    7718             :     "native function A();"
    7719             :     "native function B();"
    7720             :     "native function C();"
    7721             :     "function Foo(i) {"
    7722             :     "  if (i == 0) return A();"
    7723             :     "  if (i == 1) return B();"
    7724             :     "  if (i == 2) return C();"
    7725             :     "}";
    7726             : 
    7727             : 
    7728         738 : static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
    7729         198 :   ApiTestFuzzer::Fuzz();
    7730         198 :   if (args.IsConstructCall()) {
    7731         720 :     CHECK(args.This()
    7732             :               ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
    7733             :                     args.Data())
    7734             :               .FromJust());
    7735             :     args.GetReturnValue().SetNull();
    7736         378 :     return;
    7737             :   }
    7738             :   args.GetReturnValue().Set(args.Data());
    7739             : }
    7740             : 
    7741             : 
    7742          24 : class FunctionExtension : public Extension {
    7743             :  public:
    7744          12 :   FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
    7745             :   v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    7746             :       v8::Isolate* isolate, v8::Local<String> name) override;
    7747             : };
    7748             : 
    7749             : 
    7750             : static int lookup_count = 0;
    7751          33 : v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
    7752             :     v8::Isolate* isolate, v8::Local<String> name) {
    7753          33 :   lookup_count++;
    7754          66 :   if (name->StrictEquals(v8_str("A"))) {
    7755             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7756          22 :                                      v8::Integer::New(isolate, 8));
    7757          44 :   } else if (name->StrictEquals(v8_str("B"))) {
    7758             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7759          22 :                                      v8::Integer::New(isolate, 7));
    7760          22 :   } else if (name->StrictEquals(v8_str("C"))) {
    7761             :     return v8::FunctionTemplate::New(isolate, CallFun,
    7762          22 :                                      v8::Integer::New(isolate, 6));
    7763             :   } else {
    7764           0 :     return v8::Local<v8::FunctionTemplate>();
    7765             :   }
    7766             : }
    7767             : 
    7768             : 
    7769       25881 : THREADED_TEST(FunctionLookup) {
    7770          24 :   v8::RegisterExtension(v8::base::make_unique<FunctionExtension>());
    7771           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7772             :   static const char* exts[1] = {"functiontest"};
    7773             :   v8::ExtensionConfiguration config(1, exts);
    7774          12 :   LocalContext context(&config);
    7775           6 :   CHECK_EQ(3, lookup_count);
    7776          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7777             :             ->Equals(context.local(), CompileRun("Foo(0)"))
    7778             :             .FromJust());
    7779          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7780             :             ->Equals(context.local(), CompileRun("Foo(1)"))
    7781             :             .FromJust());
    7782          18 :   CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7783             :             ->Equals(context.local(), CompileRun("Foo(2)"))
    7784           6 :             .FromJust());
    7785           6 : }
    7786             : 
    7787             : 
    7788       25881 : THREADED_TEST(NativeFunctionConstructCall) {
    7789          24 :   v8::RegisterExtension(v8::base::make_unique<FunctionExtension>());
    7790           6 :   v8::HandleScope handle_scope(CcTest::isolate());
    7791             :   static const char* exts[1] = {"functiontest"};
    7792             :   v8::ExtensionConfiguration config(1, exts);
    7793          12 :   LocalContext context(&config);
    7794          66 :   for (int i = 0; i < 10; i++) {
    7795             :     // Run a few times to ensure that allocation of objects doesn't
    7796             :     // change behavior of a constructor function.
    7797         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 8)
    7798             :               ->Equals(context.local(), CompileRun("(new A()).data"))
    7799             :               .FromJust());
    7800         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 7)
    7801             :               ->Equals(context.local(), CompileRun("(new B()).data"))
    7802             :               .FromJust());
    7803         180 :     CHECK(v8::Integer::New(CcTest::isolate(), 6)
    7804             :               ->Equals(context.local(), CompileRun("(new C()).data"))
    7805             :               .FromJust());
    7806           6 :   }
    7807           6 : }
    7808             : 
    7809             : 
    7810             : static const char* last_location;
    7811             : static const char* last_message;
    7812          10 : void StoringErrorCallback(const char* location, const char* message) {
    7813          10 :   if (last_location == nullptr) {
    7814          10 :     last_location = location;
    7815          10 :     last_message = message;
    7816             :   }
    7817          10 : }
    7818             : 
    7819             : 
    7820             : // ErrorReporting creates a circular extensions configuration and
    7821             : // tests that the fatal error handler gets called.  This renders V8
    7822             : // unusable and therefore this test cannot be run in parallel.
    7823       25880 : TEST(ErrorReporting) {
    7824           5 :   CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
    7825             :   static const char* aDeps[] = {"B"};
    7826          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>("A", "", 1, aDeps));
    7827             :   static const char* bDeps[] = {"A"};
    7828          10 :   v8::RegisterExtension(v8::base::make_unique<Extension>("B", "", 1, bDeps));
    7829           5 :   last_location = nullptr;
    7830             :   v8::ExtensionConfiguration config(1, bDeps);
    7831           5 :   v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
    7832           5 :   CHECK(context.IsEmpty());
    7833           5 :   CHECK(last_location);
    7834           5 : }
    7835             : 
    7836             : static size_t dcheck_count;
    7837           0 : void DcheckErrorCallback(const char* file, int line, const char* message) {
    7838           0 :   last_message = message;
    7839           0 :   ++dcheck_count;
    7840           0 : }
    7841             : 
    7842       25880 : TEST(DcheckErrorHandler) {
    7843           5 :   V8::SetDcheckErrorHandler(DcheckErrorCallback);
    7844             : 
    7845           5 :   last_message = nullptr;
    7846           5 :   dcheck_count = 0;
    7847             : 
    7848             :   DCHECK(false && "w00t");
    7849             : #ifdef DEBUG
    7850             :   CHECK_EQ(dcheck_count, 1);
    7851             :   CHECK(last_message);
    7852             :   CHECK(std::string(last_message).find("w00t") != std::string::npos);
    7853             : #else
    7854             :   // The DCHECK should be a noop in non-DEBUG builds.
    7855           5 :   CHECK_EQ(dcheck_count, 0);
    7856             : #endif
    7857           5 : }
    7858             : 
    7859           6 : static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
    7860             :                                              v8::Local<Value> data) {
    7861           6 :   v8::Isolate* isolate = CcTest::isolate();
    7862           6 :   Local<Context> context = isolate->GetCurrentContext();
    7863          12 :   CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
    7864          18 :   CHECK(v8::Undefined(isolate)
    7865             :             ->Equals(context, message->GetScriptOrigin().ResourceName())
    7866             :             .FromJust());
    7867          12 :   message->GetLineNumber(context).FromJust();
    7868           6 :   message->GetSourceLine(context).ToLocalChecked();
    7869           6 : }
    7870             : 
    7871             : 
    7872       25881 : THREADED_TEST(ErrorWithMissingScriptInfo) {
    7873           6 :   LocalContext context;
    7874          12 :   v8::HandleScope scope(context->GetIsolate());
    7875           6 :   context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
    7876             :   CompileRun("throw Error()");
    7877             :   context->GetIsolate()->RemoveMessageListeners(
    7878          12 :       MissingScriptInfoMessageListener);
    7879           6 : }
    7880             : 
    7881             : 
    7882             : struct FlagAndPersistent {
    7883             :   bool flag;
    7884             :   v8::Global<v8::Object> handle;
    7885             : };
    7886             : 
    7887          80 : static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    7888          40 :   data.GetParameter()->flag = true;
    7889             :   data.GetParameter()->handle.Reset();
    7890          40 : }
    7891             : 
    7892          20 : static void IndependentWeakHandle(bool global_gc, bool interlinked) {
    7893          20 :   i::FLAG_stress_incremental_marking = false;
    7894             :   // Parallel scavenge introduces too much fragmentation.
    7895          20 :   i::FLAG_parallel_scavenge = false;
    7896          20 :   v8::Isolate* iso = CcTest::isolate();
    7897          20 :   v8::HandleScope scope(iso);
    7898          20 :   v8::Local<Context> context = Context::New(iso);
    7899             :   Context::Scope context_scope(context);
    7900             : 
    7901             :   FlagAndPersistent object_a, object_b;
    7902             : 
    7903             :   size_t big_heap_size = 0;
    7904             :   size_t big_array_size = 0;
    7905             : 
    7906             :   {
    7907          20 :     v8::HandleScope handle_scope(iso);
    7908          20 :     Local<Object> a(v8::Object::New(iso));
    7909          20 :     Local<Object> b(v8::Object::New(iso));
    7910             :     object_a.handle.Reset(iso, a);
    7911             :     object_b.handle.Reset(iso, b);
    7912          20 :     if (interlinked) {
    7913          30 :       a->Set(context, v8_str("x"), b).FromJust();
    7914          30 :       b->Set(context, v8_str("x"), a).FromJust();
    7915             :     }
    7916          20 :     if (global_gc) {
    7917          10 :       CcTest::CollectAllGarbage();
    7918             :     } else {
    7919          10 :       CcTest::CollectGarbage(i::NEW_SPACE);
    7920             :     }
    7921          20 :     v8::Local<Value> big_array = v8::Array::New(CcTest::isolate(), 5000);
    7922             :     // Verify that we created an array where the space was reserved up front.
    7923             :     big_array_size =
    7924             :         v8::internal::JSArray::cast(*v8::Utils::OpenHandle(*big_array))
    7925          40 :             ->elements()
    7926          20 :             ->Size();
    7927          20 :     CHECK_LE(20000, big_array_size);
    7928          60 :     a->Set(context, v8_str("y"), big_array).FromJust();
    7929          20 :     big_heap_size = CcTest::heap()->SizeOfObjects();
    7930             :   }
    7931             : 
    7932          20 :   object_a.flag = false;
    7933          20 :   object_b.flag = false;
    7934             :   object_a.handle.SetWeak(&object_a, &SetFlag,
    7935             :                           v8::WeakCallbackType::kParameter);
    7936             :   object_b.handle.SetWeak(&object_b, &SetFlag,
    7937             :                           v8::WeakCallbackType::kParameter);
    7938             : #if __clang__
    7939             : #pragma clang diagnostic push
    7940             : #pragma clang diagnostic ignored "-Wdeprecated"
    7941             : #endif
    7942             :   // MarkIndependent is marked deprecated but we still rely on it temporarily.
    7943          20 :   CHECK(!object_b.handle.IsIndependent());
    7944             :   object_a.handle.MarkIndependent();
    7945             :   object_b.handle.MarkIndependent();
    7946          20 :   CHECK(object_b.handle.IsIndependent());
    7947             : #if __clang__
    7948             : #pragma clang diagnostic pop
    7949             : #endif
    7950          20 :   if (global_gc) {
    7951          10 :     CcTest::CollectAllGarbage();
    7952             :   } else {
    7953          10 :     CcTest::CollectGarbage(i::NEW_SPACE);
    7954             :   }
    7955             :   // A single GC should be enough to reclaim the memory, since we are using
    7956             :   // phantom handles.
    7957          20 :   CHECK_GT(big_heap_size - big_array_size, CcTest::heap()->SizeOfObjects());
    7958          20 :   CHECK(object_a.flag);
    7959          40 :   CHECK(object_b.flag);
    7960          20 : }
    7961             : 
    7962       25880 : TEST(IndependentWeakHandle) {
    7963           5 :   IndependentWeakHandle(false, false);
    7964           5 :   IndependentWeakHandle(false, true);
    7965           5 :   IndependentWeakHandle(true, false);
    7966           5 :   IndependentWeakHandle(true, true);
    7967           5 : }
    7968             : 
    7969             : class Trivial {
    7970             :  public:
    7971          12 :   explicit Trivial(int x) : x_(x) {}
    7972             : 
    7973          36 :   int x() { return x_; }
    7974          12 :   void set_x(int x) { x_ = x; }
    7975             : 
    7976             :  private:
    7977             :   int x_;
    7978             : };
    7979             : 
    7980             : 
    7981             : class Trivial2 {
    7982             :  public:
    7983          12 :   Trivial2(int x, int y) : y_(y), x_(x) {}
    7984             : 
    7985             :   int x() { return x_; }
    7986          12 :   void set_x(int x) { x_ = x; }
    7987             : 
    7988             :   int y() { return y_; }
    7989             :   void set_y(int y) { y_ = y; }
    7990             : 
    7991             :  private:
    7992             :   int y_;
    7993             :   int x_;
    7994             : };
    7995             : 
    7996          12 : void CheckInternalFields(
    7997          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
    7998             :   v8::Persistent<v8::Object>* handle = data.GetParameter();
    7999             :   handle->Reset();
    8000             :   Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
    8001          12 :   Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
    8002          12 :   CHECK_EQ(42, t1->x());
    8003          12 :   CHECK_EQ(103, t2->x());
    8004             :   t1->set_x(1729);
    8005             :   t2->set_x(33550336);
    8006          12 : }
    8007             : 
    8008          12 : void InternalFieldCallback(bool global_gc) {
    8009          12 :   LocalContext env;
    8010          12 :   v8::Isolate* isolate = env->GetIsolate();
    8011          24 :   v8::HandleScope scope(isolate);
    8012             : 
    8013          12 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
    8014          12 :   Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
    8015             :   Trivial* t1;
    8016          24 :   Trivial2* t2;
    8017          12 :   instance_templ->SetInternalFieldCount(2);
    8018             :   v8::Persistent<v8::Object> handle;
    8019             :   {
    8020          12 :     v8::HandleScope scope(isolate);
    8021          12 :     Local<v8::Object> obj = templ->GetFunction(env.local())
    8022          12 :                                 .ToLocalChecked()
    8023          12 :                                 ->NewInstance(env.local())
    8024             :                                 .ToLocalChecked();
    8025             :     handle.Reset(isolate, obj);
    8026          12 :     CHECK_EQ(2, obj->InternalFieldCount());
    8027          12 :     CHECK(obj->GetInternalField(0)->IsUndefined());
    8028          12 :     t1 = new Trivial(42);
    8029          12 :     t2 = new Trivial2(103, 9);
    8030             : 
    8031          12 :     obj->SetAlignedPointerInInternalField(0, t1);
    8032             :     t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
    8033          12 :     CHECK_EQ(42, t1->x());
    8034             : 
    8035          12 :     obj->SetAlignedPointerInInternalField(1, t2);
    8036             :     t2 =
    8037             :         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
    8038          12 :     CHECK_EQ(103, t2->x());
    8039             : 
    8040             :     handle.SetWeak<v8::Persistent<v8::Object>>(
    8041          12 :         &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
    8042             :   }
    8043          12 :   if (global_gc) {
    8044           6 :     CcTest::CollectAllGarbage();
    8045             :   } else {
    8046           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    8047             :   }
    8048             : 
    8049          12 :   CHECK_EQ(1729, t1->x());
    8050          12 :   CHECK_EQ(33550336, t2->x());
    8051             : 
    8052          12 :   delete t1;
    8053          24 :   delete t2;
    8054          12 : }
    8055             : 
    8056       25881 : THREADED_TEST(InternalFieldCallback) {
    8057           6 :   InternalFieldCallback(false);
    8058           6 :   InternalFieldCallback(true);
    8059           6 : }
    8060             : 
    8061          24 : static void ResetUseValueAndSetFlag(
    8062          48 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8063             :   // Blink will reset the handle, and then use the other handle, so they
    8064             :   // can't use the same backing slot.
    8065             :   data.GetParameter()->handle.Reset();
    8066          24 :   data.GetParameter()->flag = true;
    8067          24 : }
    8068             : 
    8069          12 : void v8::internal::heap::HeapTester::ResetWeakHandle(bool global_gc) {
    8070             :   using v8::Context;
    8071             :   using v8::Local;
    8072             :   using v8::Object;
    8073             : 
    8074          12 :   v8::Isolate* iso = CcTest::isolate();
    8075          12 :   v8::HandleScope scope(iso);
    8076          12 :   v8::Local<Context> context = Context::New(iso);
    8077             :   Context::Scope context_scope(context);
    8078             : 
    8079             :   FlagAndPersistent object_a, object_b;
    8080             : 
    8081             :   {
    8082          12 :     v8::HandleScope handle_scope(iso);
    8083          12 :     Local<Object> a(v8::Object::New(iso));
    8084          12 :     Local<Object> b(v8::Object::New(iso));
    8085             :     object_a.handle.Reset(iso, a);
    8086             :     object_b.handle.Reset(iso, b);
    8087          12 :     if (global_gc) {
    8088           6 :       CcTest::PreciseCollectAllGarbage();
    8089             :     } else {
    8090           6 :       CcTest::CollectGarbage(i::NEW_SPACE);
    8091          12 :     }
    8092             :   }
    8093             : 
    8094          12 :   object_a.flag = false;
    8095          12 :   object_b.flag = false;
    8096             :   object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
    8097             :                           v8::WeakCallbackType::kParameter);
    8098             :   object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
    8099             :                           v8::WeakCallbackType::kParameter);
    8100          12 :   if (!global_gc) {
    8101             : #if __clang__
    8102             : #pragma clang diagnostic push
    8103             : #pragma clang diagnostic ignored "-Wdeprecated"
    8104             : #endif
    8105             :     // MarkIndependent is marked deprecated but we still rely on it temporarily.
    8106             :     object_a.handle.MarkIndependent();
    8107             :     object_b.handle.MarkIndependent();
    8108           6 :     CHECK(object_b.handle.IsIndependent());
    8109             : #if __clang__
    8110             : #pragma clang diagnostic pop
    8111             : #endif
    8112             :   }
    8113          12 :   if (global_gc) {
    8114           6 :     CcTest::PreciseCollectAllGarbage();
    8115             :   } else {
    8116           6 :     CcTest::CollectGarbage(i::NEW_SPACE);
    8117             :   }
    8118          12 :   CHECK(object_a.flag);
    8119          24 :   CHECK(object_b.flag);
    8120          12 : }
    8121             : 
    8122       25881 : THREADED_HEAP_TEST(ResetWeakHandle) {
    8123           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(false);
    8124           6 :   v8::internal::heap::HeapTester::ResetWeakHandle(true);
    8125           6 : }
    8126             : 
    8127          24 : static void InvokeScavenge() { CcTest::CollectGarbage(i::NEW_SPACE); }
    8128             : 
    8129          24 : static void InvokeMarkSweep() { CcTest::CollectAllGarbage(); }
    8130             : 
    8131          12 : static void ForceScavenge2(
    8132          12 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8133          12 :   data.GetParameter()->flag = true;
    8134             :   InvokeScavenge();
    8135          12 : }
    8136             : 
    8137          12 : static void ForceScavenge1(
    8138          24 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8139             :   data.GetParameter()->handle.Reset();
    8140             :   data.SetSecondPassCallback(ForceScavenge2);
    8141          12 : }
    8142             : 
    8143          12 : static void ForceMarkSweep2(
    8144          12 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8145          12 :   data.GetParameter()->flag = true;
    8146             :   InvokeMarkSweep();
    8147          12 : }
    8148             : 
    8149          12 : static void ForceMarkSweep1(
    8150          24 :     const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
    8151             :   data.GetParameter()->handle.Reset();
    8152             :   data.SetSecondPassCallback(ForceMarkSweep2);
    8153          12 : }
    8154             : 
    8155       25881 : THREADED_TEST(GCFromWeakCallbacks) {
    8156           6 :   v8::Isolate* isolate = CcTest::isolate();
    8157           6 :   v8::Locker locker(CcTest::isolate());
    8158          12 :   v8::HandleScope scope(isolate);
    8159           6 :   v8::Local<Context> context = Context::New(isolate);
    8160             :   Context::Scope context_scope(context);
    8161             : 
    8162             :   static const int kNumberOfGCTypes = 2;
    8163             :   typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
    8164             :   Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
    8165           6 :                                                     &ForceMarkSweep1};
    8166             : 
    8167             :   typedef void (*GCInvoker)();
    8168           6 :   GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
    8169             : 
    8170          18 :   for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
    8171          24 :     for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
    8172             :       FlagAndPersistent object;
    8173             :       {
    8174          24 :         v8::HandleScope handle_scope(isolate);
    8175          48 :         object.handle.Reset(isolate, v8::Object::New(isolate));
    8176             :       }
    8177          24 :       object.flag = false;
    8178             :       object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
    8179          24 :                             v8::WeakCallbackType::kParameter);
    8180             : #if __clang__
    8181             : #pragma clang diagnostic push
    8182             : #pragma clang diagnostic ignored "-Wdeprecated"
    8183             : #endif
    8184             :       // MarkIndependent is marked deprecated but we still rely on it
    8185             :       // temporarily.
    8186             :       object.handle.MarkIndependent();
    8187             : #if __clang__
    8188             : #pragma clang diagnostic pop
    8189             : #endif
    8190          24 :       invoke_gc[outer_gc]();
    8191          24 :       EmptyMessageQueues(isolate);
    8192          24 :       CHECK(object.flag);
    8193             :     }
    8194           6 :   }
    8195           6 : }
    8196             : 
    8197             : v8::Local<Function> args_fun;
    8198             : 
    8199             : 
    8200           6 : static void ArgumentsTestCallback(
    8201          18 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    8202           6 :   ApiTestFuzzer::Fuzz();
    8203             :   v8::Isolate* isolate = args.GetIsolate();
    8204           6 :   Local<Context> context = isolate->GetCurrentContext();
    8205           6 :   CHECK_EQ(3, args.Length());
    8206          18 :   CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
    8207          18 :   CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
    8208          18 :   CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
    8209          12 :   CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
    8210           6 :   v8::HandleScope scope(args.GetIsolate());
    8211           6 :   CcTest::CollectAllGarbage();
    8212           6 : }
    8213             : 
    8214             : 
    8215       25881 : THREADED_TEST(Arguments) {
    8216           6 :   v8::Isolate* isolate = CcTest::isolate();
    8217           6 :   v8::HandleScope scope(isolate);
    8218           6 :   v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
    8219             :   global->Set(v8_str("f"),
    8220          18 :               v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
    8221          12 :   LocalContext context(nullptr, global);
    8222             :   args_fun = context->Global()
    8223          24 :                  ->Get(context.local(), v8_str("f"))
    8224           6 :                  .ToLocalChecked()
    8225           6 :                  .As<Function>();
    8226          18 :   v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
    8227           6 : }
    8228             : 
    8229             : 
    8230             : static int p_getter_count;
    8231             : static int p_getter_count2;
    8232             : 
    8233             : 
    8234         240 : static void PGetter(Local<Name> name,
    8235             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    8236         240 :   ApiTestFuzzer::Fuzz();
    8237         240 :   p_getter_count++;
    8238         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8239         240 :   v8::Local<v8::Object> global = context->Global();
    8240         960 :   CHECK(
    8241             :       info.Holder()
    8242             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8243             :           .FromJust());
    8244         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8245         240 :     CHECK(info.This()
    8246             :               ->Equals(context,
    8247             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8248             :               .FromJust());
    8249         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8250         240 :     CHECK(info.This()
    8251             :               ->Equals(context,
    8252             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8253             :               .FromJust());
    8254         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8255         240 :     CHECK(info.This()
    8256             :               ->Equals(context,
    8257             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8258             :               .FromJust());
    8259         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8260         240 :     CHECK(info.This()
    8261             :               ->Equals(context,
    8262             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8263             :               .FromJust());
    8264             :   }
    8265         240 : }
    8266             : 
    8267             : 
    8268          12 : static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
    8269          12 :   ApiTestFuzzer::Fuzz();
    8270          12 :   LocalContext context;
    8271          84 :   CHECK(context->Global()
    8272             :             ->Set(context.local(), v8_str("o1"),
    8273             :                   obj->NewInstance(context.local()).ToLocalChecked())
    8274             :             .FromJust());
    8275             :   CompileRun(
    8276             :     "o1.__proto__ = { };"
    8277             :     "var o2 = { __proto__: o1 };"
    8278             :     "var o3 = { __proto__: o2 };"
    8279             :     "var o4 = { __proto__: o3 };"
    8280             :     "for (var i = 0; i < 10; i++) o4.p4;"
    8281             :     "for (var i = 0; i < 10; i++) o3.p3;"
    8282             :     "for (var i = 0; i < 10; i++) o2.p2;"
    8283          12 :     "for (var i = 0; i < 10; i++) o1.p1;");
    8284          12 : }
    8285             : 
    8286             : 
    8287         240 : static void PGetter2(Local<Name> name,
    8288             :                      const v8::PropertyCallbackInfo<v8::Value>& info) {
    8289         240 :   ApiTestFuzzer::Fuzz();
    8290         240 :   p_getter_count2++;
    8291         240 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    8292         240 :   v8::Local<v8::Object> global = context->Global();
    8293         960 :   CHECK(
    8294             :       info.Holder()
    8295             :           ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
    8296             :           .FromJust());
    8297         720 :   if (name->Equals(context, v8_str("p1")).FromJust()) {
    8298         240 :     CHECK(info.This()
    8299             :               ->Equals(context,
    8300             :                        global->Get(context, v8_str("o1")).ToLocalChecked())
    8301             :               .FromJust());
    8302         540 :   } else if (name->Equals(context, v8_str("p2")).FromJust()) {
    8303         240 :     CHECK(info.This()
    8304             :               ->Equals(context,
    8305             :                        global->Get(context, v8_str("o2")).ToLocalChecked())
    8306             :               .FromJust());
    8307         360 :   } else if (name->Equals(context, v8_str("p3")).FromJust()) {
    8308         240 :     CHECK(info.This()
    8309             :               ->Equals(context,
    8310             :                        global->Get(context, v8_str("o3")).ToLocalChecked())
    8311             :               .FromJust());
    8312         180 :   } else if (name->Equals(context, v8_str("p4")).FromJust()) {
    8313         240 :     CHECK(info.This()
    8314             :               ->Equals(context,
    8315             :                        global->Get(context, v8_str("o4")).ToLocalChecked())
    8316             :               .FromJust());
    8317             :   }
    8318         240 : }
    8319             : 
    8320             : 
    8321       25881 : THREADED_TEST(GetterHolders) {
    8322           6 :   v8::Isolate* isolate = CcTest::isolate();
    8323           6 :   v8::HandleScope scope(isolate);
    8324           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8325          12 :   obj->SetAccessor(v8_str("p1"), PGetter);
    8326          12 :   obj->SetAccessor(v8_str("p2"), PGetter);
    8327          12 :   obj->SetAccessor(v8_str("p3"), PGetter);
    8328          12 :   obj->SetAccessor(v8_str("p4"), PGetter);
    8329           6 :   p_getter_count = 0;
    8330           6 :   RunHolderTest(obj);
    8331           6 :   CHECK_EQ(40, p_getter_count);
    8332           6 : }
    8333             : 
    8334             : 
    8335       25881 : THREADED_TEST(PreInterceptorHolders) {
    8336           6 :   v8::Isolate* isolate = CcTest::isolate();
    8337           6 :   v8::HandleScope scope(isolate);
    8338           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    8339           6 :   obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
    8340           6 :   p_getter_count2 = 0;
    8341           6 :   RunHolderTest(obj);
    8342           6 :   CHECK_EQ(40, p_getter_count2);
    8343           6 : }
    8344             : 
    8345             : 
    8346       25881 : THREADED_TEST(ObjectInstantiation) {
    8347           6 :   v8::Isolate* isolate = CcTest::isolate();
    8348           6 :   v8::HandleScope scope(isolate);
    8349           6 :   v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
    8350          12 :   templ->SetAccessor(v8_str("t"), PGetter2);
    8351          12 :   LocalContext context;
    8352          36 :   CHECK(context->Global()
    8353             :             ->Set(context.local(), v8_str("o"),
    8354             :                   templ->NewInstance(context.local()).ToLocalChecked())
    8355             :             .FromJust());
    8356         600 :   for (int i = 0; i < 100; i++) {
    8357         600 :     v8::HandleScope inner_scope(CcTest::isolate());
    8358             :     v8::Local<v8::Object> obj =
    8359         600 :         templ->NewInstance(context.local()).ToLocalChecked();
    8360        3600 :     CHECK(!obj->Equals(context.local(), context->Global()
    8361             :                                             ->Get(context.local(), v8_str("o"))
    8362             :                                             .ToLocalChecked())
    8363             :                .FromJust());
    8364        3000 :     CHECK(
    8365             :         context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
    8366         600 :     v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
    8367        1800 :     CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
    8368        3000 :     CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
    8369         606 :   }
    8370           6 : }
    8371             : 
    8372             : 
    8373             : static int StrCmp16(uint16_t* a, uint16_t* b) {
    8374             :   while (true) {
    8375         168 :     if (*a == 0 && *b == 0) return 0;
    8376         138 :     if (*a != *b) return 0 + *a - *b;
    8377         132 :     a++;
    8378         132 :     b++;
    8379             :   }
    8380             : }
    8381             : 
    8382             : 
    8383             : static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
    8384             :   while (true) {
    8385         150 :     if (n-- == 0) return 0;
    8386         120 :     if (*a == 0 && *b == 0) return 0;
    8387         120 :     if (*a != *b) return 0 + *a - *b;
    8388         120 :     a++;
    8389         120 :     b++;
    8390             :   }
    8391             : }
    8392             : 
    8393         552 : int GetUtf8Length(v8::Isolate* isolate, Local<String> str) {
    8394         552 :   int len = str->Utf8Length(isolate);
    8395         552 :   if (len < 0) {
    8396             :     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    8397           0 :     i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
    8398           0 :     i::String::Flatten(i_isolate, istr);
    8399           0 :     len = str->Utf8Length(isolate);
    8400             :   }
    8401         552 :   return len;
    8402             : }
    8403             : 
    8404             : 
    8405       25881 : THREADED_TEST(StringWrite) {
    8406           6 :   LocalContext context;
    8407           6 :   v8::Isolate* isolate = context->GetIsolate();
    8408          12 :   v8::HandleScope scope(isolate);
    8409           6 :   v8::Local<String> str = v8_str("abcde");
    8410             :   // abc<Icelandic eth><Unicode snowman>.
    8411           6 :   v8::Local<String> str2 = v8_str("abc\xC3\xB0\xE2\x98\x83");
    8412             :   v8::Local<String> str3 =
    8413             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
    8414           6 :                               v8::NewStringType::kNormal, 7)
    8415           6 :           .ToLocalChecked();
    8416             :   // "ab" + lead surrogate + "wx" + trail surrogate + "yz"
    8417           6 :   uint16_t orphans[8] = {0x61, 0x62, 0xD800, 0x77, 0x78, 0xDC00, 0x79, 0x7A};
    8418             :   v8::Local<String> orphans_str =
    8419             :       v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
    8420           6 :                                  v8::NewStringType::kNormal, 8)
    8421           6 :           .ToLocalChecked();
    8422             :   // single lead surrogate
    8423           6 :   uint16_t lead[1] = {0xD800};
    8424             :   v8::Local<String> lead_str =
    8425             :       v8::String::NewFromTwoByte(context->GetIsolate(), lead,
    8426           6 :                                  v8::NewStringType::kNormal, 1)
    8427           6 :           .ToLocalChecked();
    8428             :   // single trail surrogate
    8429           6 :   uint16_t trail[1] = {0xDC00};
    8430             :   v8::Local<String> trail_str =
    8431             :       v8::String::NewFromTwoByte(context->GetIsolate(), trail,
    8432           6 :                                  v8::NewStringType::kNormal, 1)
    8433           6 :           .ToLocalChecked();
    8434             :   // surrogate pair
    8435           6 :   uint16_t pair[2] = {0xD800, 0xDC00};
    8436             :   v8::Local<String> pair_str =
    8437             :       v8::String::NewFromTwoByte(context->GetIsolate(), pair,
    8438           6 :                                  v8::NewStringType::kNormal, 2)
    8439           6 :           .ToLocalChecked();
    8440             :   const int kStride = 4;  // Must match stride in for loops in JS below.
    8441             :   CompileRun(
    8442             :       "var left = '';"
    8443             :       "for (var i = 0; i < 0xD800; i += 4) {"
    8444             :       "  left = left + String.fromCharCode(i);"
    8445             :       "}");
    8446             :   CompileRun(
    8447             :       "var right = '';"
    8448             :       "for (var i = 0; i < 0xD800; i += 4) {"
    8449             :       "  right = String.fromCharCode(i) + right;"
    8450             :       "}");
    8451           6 :   v8::Local<v8::Object> global = context->Global();
    8452          18 :   Local<String> left_tree = global->Get(context.local(), v8_str("left"))
    8453           6 :                                 .ToLocalChecked()
    8454             :                                 .As<String>();
    8455          18 :   Local<String> right_tree = global->Get(context.local(), v8_str("right"))
    8456           6 :                                  .ToLocalChecked()
    8457             :                                  .As<String>();
    8458             : 
    8459           6 :   CHECK_EQ(5, str2->Length());
    8460           6 :   CHECK_EQ(0xD800 / kStride, left_tree->Length());
    8461           6 :   CHECK_EQ(0xD800 / kStride, right_tree->Length());
    8462             : 
    8463             :   char buf[100];
    8464             :   char utf8buf[0xD800 * 3];
    8465             :   uint16_t wbuf[100];
    8466             :   int len;
    8467             :   int charlen;
    8468             : 
    8469             :   memset(utf8buf, 0x1, 1000);
    8470             :   len = v8::String::Empty(isolate)->WriteUtf8(isolate, utf8buf, sizeof(utf8buf),
    8471           6 :                                               &charlen);
    8472           6 :   CHECK_EQ(1, len);
    8473           6 :   CHECK_EQ(0, charlen);
    8474           6 :   CHECK_EQ(0, strcmp(utf8buf, ""));
    8475             : 
    8476             :   memset(utf8buf, 0x1, 1000);
    8477           6 :   len = str2->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen);
    8478           6 :   CHECK_EQ(9, len);
    8479           6 :   CHECK_EQ(5, charlen);
    8480           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8481             : 
    8482             :   memset(utf8buf, 0x1, 1000);
    8483           6 :   len = str2->WriteUtf8(isolate, utf8buf, 8, &charlen);
    8484           6 :   CHECK_EQ(8, len);
    8485           6 :   CHECK_EQ(5, charlen);
    8486           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83\x01", 9));
    8487             : 
    8488             :   memset(utf8buf, 0x1, 1000);
    8489           6 :   len = str2->WriteUtf8(isolate, utf8buf, 7, &charlen);
    8490           6 :   CHECK_EQ(5, len);
    8491           6 :   CHECK_EQ(4, charlen);
    8492           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8493             : 
    8494             :   memset(utf8buf, 0x1, 1000);
    8495           6 :   len = str2->WriteUtf8(isolate, utf8buf, 6, &charlen);
    8496           6 :   CHECK_EQ(5, len);
    8497           6 :   CHECK_EQ(4, charlen);
    8498           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8499             : 
    8500             :   memset(utf8buf, 0x1, 1000);
    8501           6 :   len = str2->WriteUtf8(isolate, utf8buf, 5, &charlen);
    8502           6 :   CHECK_EQ(5, len);
    8503           6 :   CHECK_EQ(4, charlen);
    8504           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\x01", 5));
    8505             : 
    8506             :   memset(utf8buf, 0x1, 1000);
    8507           6 :   len = str2->WriteUtf8(isolate, utf8buf, 4, &charlen);
    8508           6 :   CHECK_EQ(3, len);
    8509           6 :   CHECK_EQ(3, charlen);
    8510           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\x01", 4));
    8511             : 
    8512             :   memset(utf8buf, 0x1, 1000);
    8513           6 :   len = str2->WriteUtf8(isolate, utf8buf, 3, &charlen);
    8514           6 :   CHECK_EQ(3, len);
    8515           6 :   CHECK_EQ(3, charlen);
    8516           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\x01", 4));
    8517             : 
    8518             :   memset(utf8buf, 0x1, 1000);
    8519           6 :   len = str2->WriteUtf8(isolate, utf8buf, 2, &charlen);
    8520           6 :   CHECK_EQ(2, len);
    8521           6 :   CHECK_EQ(2, charlen);
    8522           6 :   CHECK_EQ(0, strncmp(utf8buf, "ab\x01", 3));
    8523             : 
    8524             :   // allow orphan surrogates by default
    8525             :   memset(utf8buf, 0x1, 1000);
    8526           6 :   len = orphans_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen);
    8527           6 :   CHECK_EQ(13, len);
    8528           6 :   CHECK_EQ(8, charlen);
    8529           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\xED\xA0\x80wx\xED\xB0\x80yz"));
    8530             : 
    8531             :   // replace orphan surrogates with Unicode replacement character
    8532             :   memset(utf8buf, 0x1, 1000);
    8533             :   len = orphans_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8534           6 :                                String::REPLACE_INVALID_UTF8);
    8535           6 :   CHECK_EQ(13, len);
    8536           6 :   CHECK_EQ(8, charlen);
    8537           6 :   CHECK_EQ(0, strcmp(utf8buf, "ab\xEF\xBF\xBDwx\xEF\xBF\xBDyz"));
    8538             : 
    8539             :   // replace single lead surrogate with Unicode replacement character
    8540             :   memset(utf8buf, 0x1, 1000);
    8541             :   len = lead_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8542           6 :                             String::REPLACE_INVALID_UTF8);
    8543           6 :   CHECK_EQ(4, len);
    8544           6 :   CHECK_EQ(1, charlen);
    8545           6 :   CHECK_EQ(0, strcmp(utf8buf, "\xEF\xBF\xBD"));
    8546             : 
    8547             :   // replace single trail surrogate with Unicode replacement character
    8548             :   memset(utf8buf, 0x1, 1000);
    8549             :   len = trail_str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8550           6 :                              String::REPLACE_INVALID_UTF8);
    8551           6 :   CHECK_EQ(4, len);
    8552           6 :   CHECK_EQ(1, charlen);
    8553           6 :   CHECK_EQ(0, strcmp(utf8buf, "\xEF\xBF\xBD"));
    8554             : 
    8555             :   // do not replace / write anything if surrogate pair does not fit the buffer
    8556             :   // space
    8557             :   memset(utf8buf, 0x1, 1000);
    8558             :   len = pair_str->WriteUtf8(isolate, utf8buf, 3, &charlen,
    8559           6 :                             String::REPLACE_INVALID_UTF8);
    8560           6 :   CHECK_EQ(0, len);
    8561           6 :   CHECK_EQ(0, charlen);
    8562             : 
    8563             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8564           6 :   len = GetUtf8Length(isolate, left_tree);
    8565             :   int utf8_expected =
    8566             :       (0x80 + (0x800 - 0x80) * 2 + (0xD800 - 0x800) * 3) / kStride;
    8567           6 :   CHECK_EQ(utf8_expected, len);
    8568           6 :   len = left_tree->WriteUtf8(isolate, utf8buf, utf8_expected, &charlen);
    8569           6 :   CHECK_EQ(utf8_expected, len);
    8570           6 :   CHECK_EQ(0xD800 / kStride, charlen);
    8571          12 :   CHECK_EQ(0xED, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
    8572          12 :   CHECK_EQ(0x9F, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
    8573          12 :   CHECK_EQ(0xC0 - kStride,
    8574             :            static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
    8575           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8576             : 
    8577             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8578           6 :   len = GetUtf8Length(isolate, right_tree);
    8579           6 :   CHECK_EQ(utf8_expected, len);
    8580           6 :   len = right_tree->WriteUtf8(isolate, utf8buf, utf8_expected, &charlen);
    8581           6 :   CHECK_EQ(utf8_expected, len);
    8582           6 :   CHECK_EQ(0xD800 / kStride, charlen);
    8583          12 :   CHECK_EQ(0xED, static_cast<unsigned char>(utf8buf[0]));
    8584          12 :   CHECK_EQ(0x9F, static_cast<unsigned char>(utf8buf[1]));
    8585          12 :   CHECK_EQ(0xC0 - kStride, static_cast<unsigned char>(utf8buf[2]));
    8586           6 :   CHECK_EQ(1, utf8buf[utf8_expected]);
    8587             : 
    8588             :   memset(buf, 0x1, sizeof(buf));
    8589             :   memset(wbuf, 0x1, sizeof(wbuf));
    8590           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf));
    8591           6 :   CHECK_EQ(5, len);
    8592           6 :   len = str->Write(isolate, wbuf);
    8593           6 :   CHECK_EQ(5, len);
    8594           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8595           6 :   uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8596           6 :   CHECK_EQ(0, StrCmp16(answer1, wbuf));
    8597             : 
    8598             :   memset(buf, 0x1, sizeof(buf));
    8599             :   memset(wbuf, 0x1, sizeof(wbuf));
    8600           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 4);
    8601           6 :   CHECK_EQ(4, len);
    8602           6 :   len = str->Write(isolate, wbuf, 0, 4);
    8603           6 :   CHECK_EQ(4, len);
    8604           6 :   CHECK_EQ(0, strncmp("abcd\x01", buf, 5));
    8605           6 :   uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
    8606           6 :   CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
    8607             : 
    8608             :   memset(buf, 0x1, sizeof(buf));
    8609             :   memset(wbuf, 0x1, sizeof(wbuf));
    8610           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 5);
    8611           6 :   CHECK_EQ(5, len);
    8612           6 :   len = str->Write(isolate, wbuf, 0, 5);
    8613           6 :   CHECK_EQ(5, len);
    8614           6 :   CHECK_EQ(0, strncmp("abcde\x01", buf, 6));
    8615           6 :   uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
    8616           6 :   CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
    8617             : 
    8618             :   memset(buf, 0x1, sizeof(buf));
    8619             :   memset(wbuf, 0x1, sizeof(wbuf));
    8620           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 6);
    8621           6 :   CHECK_EQ(5, len);
    8622           6 :   len = str->Write(isolate, wbuf, 0, 6);
    8623           6 :   CHECK_EQ(5, len);
    8624           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8625           6 :   uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8626           6 :   CHECK_EQ(0, StrCmp16(answer4, wbuf));
    8627             : 
    8628             :   memset(buf, 0x1, sizeof(buf));
    8629             :   memset(wbuf, 0x1, sizeof(wbuf));
    8630           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, -1);
    8631           6 :   CHECK_EQ(1, len);
    8632           6 :   len = str->Write(isolate, wbuf, 4, -1);
    8633           6 :   CHECK_EQ(1, len);
    8634           6 :   CHECK_EQ(0, strcmp("e", buf));
    8635           6 :   uint16_t answer5[] = {'e', '\0'};
    8636           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8637             : 
    8638             :   memset(buf, 0x1, sizeof(buf));
    8639             :   memset(wbuf, 0x1, sizeof(wbuf));
    8640           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, 6);
    8641           6 :   CHECK_EQ(1, len);
    8642           6 :   len = str->Write(isolate, wbuf, 4, 6);
    8643           6 :   CHECK_EQ(1, len);
    8644           6 :   CHECK_EQ(0, strcmp("e", buf));
    8645           6 :   CHECK_EQ(0, StrCmp16(answer5, wbuf));
    8646             : 
    8647             :   memset(buf, 0x1, sizeof(buf));
    8648             :   memset(wbuf, 0x1, sizeof(wbuf));
    8649           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 4, 1);
    8650           6 :   CHECK_EQ(1, len);
    8651           6 :   len = str->Write(isolate, wbuf, 4, 1);
    8652           6 :   CHECK_EQ(1, len);
    8653           6 :   CHECK_EQ(0, strncmp("e\x01", buf, 2));
    8654           6 :   uint16_t answer6[] = {'e', 0x101};
    8655           6 :   CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
    8656             : 
    8657             :   memset(buf, 0x1, sizeof(buf));
    8658             :   memset(wbuf, 0x1, sizeof(wbuf));
    8659           6 :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 3, 1);
    8660           6 :   CHECK_EQ(1, len);
    8661           6 :   len = str->Write(isolate, wbuf, 3, 1);
    8662           6 :   CHECK_EQ(1, len);
    8663           6 :   CHECK_EQ(0, strncmp("d\x01", buf, 2));
    8664           6 :   uint16_t answer7[] = {'d', 0x101};
    8665           6 :   CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
    8666             : 
    8667             :   memset(wbuf, 0x1, sizeof(wbuf));
    8668           6 :   wbuf[5] = 'X';
    8669           6 :   len = str->Write(isolate, wbuf, 0, 6, String::NO_NULL_TERMINATION);
    8670           6 :   CHECK_EQ(5, len);
    8671          12 :   CHECK_EQ('X', wbuf[5]);
    8672           6 :   uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
    8673           6 :   uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
    8674           6 :   CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
    8675           6 :   CHECK_NE(0, StrCmp16(answer8b, wbuf));
    8676           6 :   wbuf[5] = '\0';
    8677           6 :   CHECK_EQ(0, StrCmp16(answer8b, wbuf));
    8678             : 
    8679             :   memset(buf, 0x1, sizeof(buf));
    8680           6 :   buf[5] = 'X';
    8681             :   len = str->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf), 0, 6,
    8682           6 :                           String::NO_NULL_TERMINATION);
    8683           6 :   CHECK_EQ(5, len);
    8684           6 :   CHECK_EQ('X', buf[5]);
    8685           6 :   CHECK_EQ(0, strncmp("abcde", buf, 5));
    8686           6 :   CHECK_NE(0, strcmp("abcde", buf));
    8687           6 :   buf[5] = '\0';
    8688           6 :   CHECK_EQ(0, strcmp("abcde", buf));
    8689             : 
    8690             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8691           6 :   utf8buf[8] = 'X';
    8692             :   len = str2->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8693           6 :                         String::NO_NULL_TERMINATION);
    8694           6 :   CHECK_EQ(8, len);
    8695           6 :   CHECK_EQ('X', utf8buf[8]);
    8696           6 :   CHECK_EQ(5, charlen);
    8697           6 :   CHECK_EQ(0, strncmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83", 8));
    8698           6 :   CHECK_NE(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8699           6 :   utf8buf[8] = '\0';
    8700           6 :   CHECK_EQ(0, strcmp(utf8buf, "abc\xC3\xB0\xE2\x98\x83"));
    8701             : 
    8702             :   memset(utf8buf, 0x1, sizeof(utf8buf));
    8703           6 :   utf8buf[5] = 'X';
    8704             :   len = str->WriteUtf8(isolate, utf8buf, sizeof(utf8buf), &charlen,
    8705           6 :                        String::NO_NULL_TERMINATION);
    8706           6 :   CHECK_EQ(5, len);
    8707           6 :   CHECK_EQ('X', utf8buf[5]);  // Test that the sixth character is untouched.
    8708           6 :   CHECK_EQ(5, charlen);
    8709           6 :   utf8buf[5] = '\0';
    8710           6 :   CHECK_EQ(0, strcmp(utf8buf, "abcde"));
    8711             : 
    8712             :   memset(buf, 0x1, sizeof(buf));
    8713           6 :   len = str3->WriteOneByte(isolate, reinterpret_cast<uint8_t*>(buf));
    8714           6 :   CHECK_EQ(7, len);
    8715           6 :   CHECK_EQ(0, strcmp("abc", buf));
    8716           6 :   CHECK_EQ(0, buf[3]);
    8717           6 :   CHECK_EQ(0, strcmp("def", buf + 4));
    8718             : 
    8719           6 :   CHECK_EQ(0, str->WriteOneByte(isolate, nullptr, 0, 0,
    8720             :                                 String::NO_NULL_TERMINATION));
    8721           6 :   CHECK_EQ(0, str->WriteUtf8(isolate, nullptr, 0, nullptr,
    8722             :                              String::NO_NULL_TERMINATION));
    8723          12 :   CHECK_EQ(0, str->Write(isolate, nullptr, 0, 0, String::NO_NULL_TERMINATION));
    8724           6 : }
    8725             : 
    8726             : 
    8727          12 : static void Utf16Helper(
    8728             :     LocalContext& context,  // NOLINT
    8729             :     const char* name,
    8730             :     const char* lengths_name,
    8731             :     int len) {
    8732             :   Local<v8::Array> a = Local<v8::Array>::Cast(
    8733          60 :       context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
    8734             :   Local<v8::Array> alens =
    8735             :       Local<v8::Array>::Cast(context->Global()
    8736          48 :                                  ->Get(context.local(), v8_str(lengths_name))
    8737          12 :                                  .ToLocalChecked());
    8738         552 :   for (int i = 0; i < len; i++) {
    8739             :     Local<v8::String> string =
    8740        1080 :         Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
    8741             :     Local<v8::Number> expected_len = Local<v8::Number>::Cast(
    8742         540 :         alens->Get(context.local(), i).ToLocalChecked());
    8743         540 :     int length = GetUtf8Length(context->GetIsolate(), string);
    8744         540 :     CHECK_EQ(static_cast<int>(expected_len->Value()), length);
    8745             :   }
    8746          12 : }
    8747             : 
    8748           6 : void TestUtf8DecodingAgainstReference(
    8749             :     v8::Isolate* isolate, const char* cases[],
    8750         474 :     const std::vector<std::vector<uint16_t>>& unicode_expected) {
    8751         132 :   for (size_t test_ix = 0; test_ix < unicode_expected.size(); ++test_ix) {
    8752          60 :     v8::Local<String> str = v8_str(cases[test_ix]);
    8753         180 :     CHECK_EQ(unicode_expected[test_ix].size(), str->Length());
    8754             : 
    8755          60 :     std::unique_ptr<uint16_t[]> buffer(new uint16_t[str->Length()]);
    8756          60 :     str->Write(isolate, buffer.get(), 0, -1, String::NO_NULL_TERMINATION);
    8757             : 
    8758        1044 :     for (size_t i = 0; i < unicode_expected[test_ix].size(); ++i) {
    8759         576 :       CHECK_EQ(unicode_expected[test_ix][i], buffer[i]);
    8760             :     }
    8761             :   }
    8762           6 : }
    8763             : 
    8764       25881 : THREADED_TEST(OverlongSequencesAndSurrogates) {
    8765           6 :   LocalContext context;
    8766          12 :   v8::HandleScope scope(context->GetIsolate());
    8767             : 
    8768             :   const char* cases[] = {
    8769             :       // Overlong 2-byte sequence.
    8770             :       "X\xc0\xbfY\0",
    8771             :       // Another overlong 2-byte sequence.
    8772             :       "X\xc1\xbfY\0",
    8773             :       // Overlong 3-byte sequence.
    8774             :       "X\xe0\x9f\xbfY\0",
    8775             :       // Overlong 4-byte sequence.
    8776             :       "X\xf0\x89\xbf\xbfY\0",
    8777             :       // Invalid 3-byte sequence (reserved for surrogates).
    8778             :       "X\xed\xa0\x80Y\0",
    8779             :       // Invalid 4-bytes sequence (value out of range).
    8780             :       "X\xf4\x90\x80\x80Y\0",
    8781             : 
    8782             :       // Start of an overlong 3-byte sequence but not enough continuation bytes.
    8783             :       "X\xe0\x9fY\0",
    8784             :       // Start of an overlong 4-byte sequence but not enough continuation bytes.
    8785             :       "X\xf0\x89\xbfY\0",
    8786             :       // Start of an invalid 3-byte sequence (reserved for surrogates) but not
    8787             :       // enough continuation bytes.
    8788             :       "X\xed\xa0Y\0",
    8789             :       // Start of an invalid 4-bytes sequence (value out of range) but not
    8790             :       // enough continuation bytes.
    8791             :       "X\xf4\x90\x80Y\0",
    8792           6 :   };
    8793             :   const std::vector<std::vector<uint16_t>> unicode_expected = {
    8794             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8795             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8796             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8797             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8798             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8799             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8800             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8801             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8802             :       {0x58, 0xFFFD, 0xFFFD, 0x59},
    8803             :       {0x58, 0xFFFD, 0xFFFD, 0xFFFD, 0x59},
    8804          12 :   };
    8805          12 :   CHECK_EQ(unicode_expected.size(), arraysize(cases));
    8806             :   TestUtf8DecodingAgainstReference(context->GetIsolate(), cases,
    8807          12 :                                    unicode_expected);
    8808           6 : }
    8809             : 
    8810       25881 : THREADED_TEST(Utf16) {
    8811           6 :   LocalContext context;
    8812          12 :   v8::HandleScope scope(context->GetIsolate());
    8813             :   CompileRun(
    8814             :       "var pad = '01234567890123456789';"
    8815             :       "var p = [];"
    8816             :       "var plens = [20, 3, 3];"
    8817             :       "p.push('01234567890123456789');"
    8818             :       "var lead = 0xD800;"
    8819             :       "var trail = 0xDC00;"
    8820             :       "p.push(String.fromCharCode(0xD800));"
    8821             :       "p.push(String.fromCharCode(0xDC00));"
    8822             :       "var a = [];"
    8823             :       "var b = [];"
    8824             :       "var c = [];"
    8825             :       "var alens = [];"
    8826             :       "for (var i = 0; i < 3; i++) {"
    8827             :       "  p[1] = String.fromCharCode(lead++);"
    8828             :       "  for (var j = 0; j < 3; j++) {"
    8829             :       "    p[2] = String.fromCharCode(trail++);"
    8830             :       "    a.push(p[i] + p[j]);"
    8831             :       "    b.push(p[i] + p[j]);"
    8832             :       "    c.push(p[i] + p[j]);"
    8833             :       "    alens.push(plens[i] + plens[j]);"
    8834             :       "  }"
    8835             :       "}"
    8836             :       "alens[5] -= 2;"  // Here the surrogate pairs match up.
    8837             :       "var a2 = [];"
    8838             :       "var b2 = [];"
    8839             :       "var c2 = [];"
    8840             :       "var a2lens = [];"
    8841             :       "for (var m = 0; m < 9; m++) {"
    8842             :       "  for (var n = 0; n < 9; n++) {"
    8843             :       "    a2.push(a[m] + a[n]);"
    8844             :       "    b2.push(b[m] + b[n]);"
    8845             :       "    var newc = 'x' + c[m] + c[n] + 'y';"
    8846             :       "    c2.push(newc.substring(1, newc.length - 1));"
    8847             :       "    var utf = alens[m] + alens[n];"  // And here.
    8848             :                                             // The 'n's that start with 0xDC..
    8849             :                                             // are 6-8 The 'm's that end with
    8850             :                                             // 0xD8.. are 1, 4 and 7
    8851             :       "    if ((m % 3) == 1 && n >= 6) utf -= 2;"
    8852             :       "    a2lens.push(utf);"
    8853             :       "  }"
    8854             :       "}");
    8855           6 :   Utf16Helper(context, "a", "alens", 9);
    8856          12 :   Utf16Helper(context, "a2", "a2lens", 81);
    8857           6 : }
    8858             : 
    8859             : 
    8860          42 : static bool SameSymbol(Local<String> s1, Local<String> s2) {
    8861             :   i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
    8862             :   i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
    8863          42 :   return *is1 == *is2;
    8864             : }
    8865             : 
    8866             : 
    8867       25881 : THREADED_TEST(Utf16Symbol) {
    8868           6 :   LocalContext context;
    8869          12 :   v8::HandleScope scope(context->GetIsolate());
    8870             : 
    8871             :   Local<String> symbol1 =
    8872             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8873           6 :                               v8::NewStringType::kInternalized)
    8874          12 :           .ToLocalChecked();
    8875             :   Local<String> symbol2 =
    8876             :       v8::String::NewFromUtf8(context->GetIsolate(), "abc",
    8877           6 :                               v8::NewStringType::kInternalized)
    8878          12 :           .ToLocalChecked();
    8879           6 :   CHECK(SameSymbol(symbol1, symbol2));
    8880             : 
    8881             :   CompileRun(
    8882             :       "var sym0 = 'benedictus';"
    8883             :       "var sym0b = 'S\xC3\xB8ren';"
    8884             :       "var sym1 = '\xED\xA0\x81\xED\xB0\x87';"
    8885             :       "var sym2 = '\xF0\x90\x90\x88';"
    8886             :       "var sym3 = 'x\xED\xA0\x81\xED\xB0\x87';"
    8887             :       "var sym4 = 'x\xF0\x90\x90\x88';"
    8888             :       "if (sym1.length != 2) throw sym1;"
    8889             :       "if (sym1.charCodeAt(1) != 0xDC07) throw sym1.charCodeAt(1);"
    8890             :       "if (sym2.length != 2) throw sym2;"
    8891             :       "if (sym2.charCodeAt(1) != 0xDC08) throw sym2.charCodeAt(2);"
    8892             :       "if (sym3.length != 3) throw sym3;"
    8893             :       "if (sym3.charCodeAt(2) != 0xDC07) throw sym1.charCodeAt(2);"
    8894             :       "if (sym4.length != 3) throw sym4;"
    8895             :       "if (sym4.charCodeAt(2) != 0xDC08) throw sym2.charCodeAt(2);");
    8896             :   Local<String> sym0 =
    8897             :       v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
    8898           6 :                               v8::NewStringType::kInternalized)
    8899          12 :           .ToLocalChecked();
    8900             :   Local<String> sym0b =
    8901             :       v8::String::NewFromUtf8(context->GetIsolate(), "S\xC3\xB8ren",
    8902           6 :                               v8::NewStringType::kInternalized)
    8903          12 :           .ToLocalChecked();
    8904             :   Local<String> sym1 =
    8905             :       v8::String::NewFromUtf8(context->GetIsolate(), "\xED\xA0\x81\xED\xB0\x87",
    8906           6 :                               v8::NewStringType::kInternalized)
    8907          12 :           .ToLocalChecked();
    8908             :   Local<String> sym2 =
    8909             :       v8::String::NewFromUtf8(context->GetIsolate(), "\xF0\x90\x90\x88",
    8910           6 :                               v8::NewStringType::kInternalized)
    8911          12 :           .ToLocalChecked();
    8912             :   Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
    8913             :                                                "x\xED\xA0\x81\xED\xB0\x87",
    8914           6 :                                                v8::NewStringType::kInternalized)
    8915          12 :                            .ToLocalChecked();
    8916             :   Local<String> sym4 =
    8917             :       v8::String::NewFromUtf8(context->GetIsolate(), "x\xF0\x90\x90\x88",
    8918           6 :                               v8::NewStringType::kInternalized)
    8919          12 :           .ToLocalChecked();
    8920           6 :   v8::Local<v8::Object> global = context->Global();
    8921             :   Local<Value> s0 =
    8922          18 :       global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
    8923             :   Local<Value> s0b =
    8924          18 :       global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
    8925             :   Local<Value> s1 =
    8926          18 :       global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
    8927             :   Local<Value> s2 =
    8928          18 :       global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
    8929             :   Local<Value> s3 =
    8930          18 :       global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
    8931             :   Local<Value> s4 =
    8932          18 :       global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
    8933           6 :   CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
    8934           6 :   CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
    8935           6 :   CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
    8936           6 :   CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
    8937           6 :   CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
    8938          12 :   CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
    8939           6 : }
    8940             : 
    8941             : 
    8942       25881 : THREADED_TEST(Utf16MissingTrailing) {
    8943           6 :   LocalContext context;
    8944          12 :   v8::HandleScope scope(context->GetIsolate());
    8945             : 
    8946             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8947             :   int size = 1024 * 64;
    8948           6 :   uint8_t* buffer = new uint8_t[size];
    8949       98310 :   for (int i = 0; i < size; i += 4) {
    8950       98304 :     buffer[i] = 0xF0;
    8951       98304 :     buffer[i + 1] = 0x9D;
    8952       98304 :     buffer[i + 2] = 0x80;
    8953       98304 :     buffer[i + 3] = 0x9E;
    8954             :   }
    8955             : 
    8956             :   // Now invoke the decoder without last 3 bytes
    8957             :   v8::Local<v8::String> str =
    8958             :       v8::String::NewFromUtf8(
    8959             :           context->GetIsolate(), reinterpret_cast<char*>(buffer),
    8960           6 :           v8::NewStringType::kNormal, size - 3).ToLocalChecked();
    8961             :   USE(str);
    8962          12 :   delete[] buffer;
    8963           6 : }
    8964             : 
    8965             : 
    8966       25881 : THREADED_TEST(Utf16Trailing3Byte) {
    8967           6 :   LocalContext context;
    8968           6 :   v8::Isolate* isolate = context->GetIsolate();
    8969          12 :   v8::HandleScope scope(isolate);
    8970             : 
    8971             :   // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
    8972             :   int size = 1024 * 63;
    8973           6 :   uint8_t* buffer = new uint8_t[size];
    8974      129030 :   for (int i = 0; i < size; i += 3) {
    8975      129024 :     buffer[i] = 0xE2;
    8976      129024 :     buffer[i + 1] = 0x80;
    8977      129024 :     buffer[i + 2] = 0xA6;
    8978             :   }
    8979             : 
    8980             :   // Now invoke the decoder without last 3 bytes
    8981             :   v8::Local<v8::String> str =
    8982             :       v8::String::NewFromUtf8(isolate, reinterpret_cast<char*>(buffer),
    8983             :                               v8::NewStringType::kNormal, size)
    8984           6 :           .ToLocalChecked();
    8985             : 
    8986          12 :   v8::String::Value value(isolate, str);
    8987           6 :   CHECK_EQ(value.length(), size / 3);
    8988          12 :   CHECK_EQ((*value)[value.length() - 1], 0x2026);
    8989             : 
    8990          12 :   delete[] buffer;
    8991           6 : }
    8992             : 
    8993             : 
    8994       25881 : THREADED_TEST(ToArrayIndex) {
    8995           6 :   LocalContext context;
    8996           6 :   v8::Isolate* isolate = context->GetIsolate();
    8997          12 :   v8::HandleScope scope(isolate);
    8998             : 
    8999           6 :   v8::Local<String> str = v8_str("42");
    9000           6 :   v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
    9001           6 :   CHECK(!index.IsEmpty());
    9002          18 :   CHECK_EQ(42.0,
    9003             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9004           6 :   str = v8_str("42asdf");
    9005           6 :   index = str->ToArrayIndex(context.local());
    9006           6 :   CHECK(index.IsEmpty());
    9007           6 :   str = v8_str("-42");
    9008           6 :   index = str->ToArrayIndex(context.local());
    9009           6 :   CHECK(index.IsEmpty());
    9010           6 :   str = v8_str("4294967294");
    9011           6 :   index = str->ToArrayIndex(context.local());
    9012           6 :   CHECK(!index.IsEmpty());
    9013          18 :   CHECK_EQ(4294967294.0,
    9014             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9015           6 :   v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
    9016           6 :   index = num->ToArrayIndex(context.local());
    9017           6 :   CHECK(!index.IsEmpty());
    9018          18 :   CHECK_EQ(1.0,
    9019             :            index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
    9020           6 :   num = v8::Number::New(isolate, -1);
    9021           6 :   index = num->ToArrayIndex(context.local());
    9022           6 :   CHECK(index.IsEmpty());
    9023           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
    9024          12 :   index = obj->ToArrayIndex(context.local());
    9025          12 :   CHECK(index.IsEmpty());
    9026           6 : }
    9027             : 
    9028           6 : static v8::MaybeLocal<Value> PrepareStackTrace42(v8::Local<Context> context,
    9029             :                                                  v8::Local<Value> error,
    9030             :                                                  v8::Local<Array> trace) {
    9031           6 :   return v8::Number::New(context->GetIsolate(), 42);
    9032             : }
    9033             : 
    9034           6 : static v8::MaybeLocal<Value> PrepareStackTraceThrow(v8::Local<Context> context,
    9035             :                                                     v8::Local<Value> error,
    9036             :                                                     v8::Local<Array> trace) {
    9037           6 :   v8::Isolate* isolate = context->GetIsolate();
    9038           6 :   v8::Local<String> message = v8_str("42");
    9039           6 :   isolate->ThrowException(v8::Exception::Error(message));
    9040           6 :   return v8::MaybeLocal<Value>();
    9041             : }
    9042             : 
    9043       25881 : THREADED_TEST(IsolatePrepareStackTrace) {
    9044           6 :   LocalContext context;
    9045           6 :   v8::Isolate* isolate = context->GetIsolate();
    9046          12 :   v8::HandleScope scope(isolate);
    9047             : 
    9048           6 :   isolate->SetPrepareStackTraceCallback(PrepareStackTrace42);
    9049             : 
    9050             :   v8::Local<Value> v = CompileRun("new Error().stack");
    9051             : 
    9052           6 :   CHECK(v->IsNumber());
    9053          18 :   CHECK_EQ(v.As<v8::Number>()->Int32Value(context.local()).FromJust(), 42);
    9054           6 : }
    9055             : 
    9056       25881 : THREADED_TEST(IsolatePrepareStackTraceThrow) {
    9057           6 :   LocalContext context;
    9058           6 :   v8::Isolate* isolate = context->GetIsolate();
    9059          12 :   v8::HandleScope scope(isolate);
    9060             : 
    9061           6 :   isolate->SetPrepareStackTraceCallback(PrepareStackTraceThrow);
    9062             : 
    9063             :   v8::Local<Value> v = CompileRun("try { new Error().stack } catch (e) { e }");
    9064             : 
    9065           6 :   CHECK(v->IsNativeError());
    9066             : 
    9067          12 :   v8::Local<String> message = v8::Exception::CreateMessage(isolate, v)->Get();
    9068             : 
    9069          18 :   CHECK(message->StrictEquals(v8_str("Uncaught Error: 42")));
    9070           6 : }
    9071             : 
    9072       25881 : THREADED_TEST(ErrorConstruction) {
    9073           6 :   LocalContext context;
    9074          12 :   v8::HandleScope scope(context->GetIsolate());
    9075             : 
    9076           6 :   v8::Local<String> foo = v8_str("foo");
    9077           6 :   v8::Local<String> message = v8_str("message");
    9078           6 :   v8::Local<Value> range_error = v8::Exception::RangeError(foo);
    9079           6 :   CHECK(range_error->IsObject());
    9080          24 :   CHECK(range_error.As<v8::Object>()
    9081             :             ->Get(context.local(), message)
    9082             :             .ToLocalChecked()
    9083             :             ->Equals(context.local(), foo)
    9084             :             .FromJust());
    9085           6 :   v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
    9086           6 :   CHECK(reference_error->IsObject());
    9087          24 :   CHECK(reference_error.As<v8::Object>()
    9088             :             ->Get(context.local(), message)
    9089             :             .ToLocalChecked()
    9090             :             ->Equals(context.local(), foo)
    9091             :             .FromJust());
    9092           6 :   v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
    9093           6 :   CHECK(syntax_error->IsObject());
    9094          24 :   CHECK(syntax_error.As<v8::Object>()
    9095             :             ->Get(context.local(), message)
    9096             :             .ToLocalChecked()
    9097             :             ->Equals(context.local(), foo)
    9098             :             .FromJust());
    9099           6 :   v8::Local<Value> type_error = v8::Exception::TypeError(foo);
    9100           6 :   CHECK(type_error->IsObject());
    9101          24 :   CHECK(type_error.As<v8::Object>()
    9102             :             ->Get(context.local(), message)
    9103             :             .ToLocalChecked()
    9104             :             ->Equals(context.local(), foo)
    9105             :             .FromJust());
    9106           6 :   v8::Local<Value> error = v8::Exception::Error(foo);
    9107           6 :   CHECK(error->IsObject());
    9108          24 :   CHECK(error.As<v8::Object>()
    9109             :             ->Get(context.local(), message)
    9110             :             .ToLocalChecked()
    9111             :             ->Equals(context.local(), foo)
    9112           6 :             .FromJust());
    9113           6 : }
    9114             : 
    9115             : 
    9116          48 : static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9117          12 :   ApiTestFuzzer::Fuzz();
    9118          12 :   v8::Local<String> foo = v8_str("foo");
    9119          12 :   v8::Local<String> message = v8_str("message");
    9120          12 :   v8::Local<Value> error = v8::Exception::Error(foo);
    9121          12 :   CHECK(error->IsObject());
    9122          12 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9123          36 :   CHECK(error.As<v8::Object>()
    9124             :             ->Get(context, message)
    9125             :             .ToLocalChecked()
    9126             :             ->Equals(context, foo)
    9127             :             .FromJust());
    9128          12 :   info.GetIsolate()->ThrowException(error);
    9129             :   info.GetReturnValue().SetUndefined();
    9130          12 : }
    9131             : 
    9132             : 
    9133       25881 : THREADED_TEST(ExceptionCreateMessage) {
    9134           6 :   LocalContext context;
    9135          12 :   v8::HandleScope scope(context->GetIsolate());
    9136           6 :   v8::Local<String> foo_str = v8_str("foo");
    9137           6 :   v8::Local<String> message_str = v8_str("message");
    9138             : 
    9139           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
    9140             : 
    9141             :   Local<v8::FunctionTemplate> fun =
    9142           6 :       v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
    9143           6 :   v8::Local<v8::Object> global = context->Global();
    9144          36 :   CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
    9145             :                     fun->GetFunction(context.local()).ToLocalChecked())
    9146             :             .FromJust());
    9147             : 
    9148          12 :   TryCatch try_catch(context->GetIsolate());
    9149             :   CompileRun(
    9150             :       "function f1() {\n"
    9151             :       "  throwV8Exception();\n"
    9152             :       "};\n"
    9153             :       "f1();");
    9154           6 :   CHECK(try_catch.HasCaught());
    9155             : 
    9156           6 :   v8::Local<v8::Value> error = try_catch.Exception();
    9157           6 :   CHECK(error->IsObject());
    9158          24 :   CHECK(error.As<v8::Object>()
    9159             :             ->Get(context.local(), message_str)
    9160             :             .ToLocalChecked()
    9161             :             ->Equals(context.local(), foo_str)
    9162             :             .FromJust());
    9163             : 
    9164             :   v8::Local<v8::Message> message =
    9165           6 :       v8::Exception::CreateMessage(context->GetIsolate(), error);
    9166           6 :   CHECK(!message.IsEmpty());
    9167          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    9168          12 :   CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
    9169             : 
    9170           6 :   v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
    9171           6 :   CHECK(!stackTrace.IsEmpty());
    9172           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    9173             : 
    9174           6 :   stackTrace = v8::Exception::GetStackTrace(error);
    9175           6 :   CHECK(!stackTrace.IsEmpty());
    9176           6 :   CHECK_EQ(2, stackTrace->GetFrameCount());
    9177             : 
    9178           6 :   context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
    9179             : 
    9180             :   // Now check message location when SetCaptureStackTraceForUncaughtExceptions
    9181             :   // is false.
    9182           6 :   try_catch.Reset();
    9183             : 
    9184             :   CompileRun(
    9185             :       "function f2() {\n"
    9186             :       "  return throwV8Exception();\n"
    9187             :       "};\n"
    9188             :       "f2();");
    9189           6 :   CHECK(try_catch.HasCaught());
    9190             : 
    9191           6 :   error = try_catch.Exception();
    9192           6 :   CHECK(error->IsObject());
    9193          24 :   CHECK(error.As<v8::Object>()
    9194             :             ->Get(context.local(), message_str)
    9195             :             .ToLocalChecked()
    9196             :             ->Equals(context.local(), foo_str)
    9197             :             .FromJust());
    9198             : 
    9199           6 :   message = v8::Exception::CreateMessage(context->GetIsolate(), error);
    9200           6 :   CHECK(!message.IsEmpty());
    9201          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
    9202          12 :   CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
    9203             : 
    9204             :   // Should be empty stack trace.
    9205           6 :   stackTrace = message->GetStackTrace();
    9206           6 :   CHECK(stackTrace.IsEmpty());
    9207          18 :   CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
    9208           6 : }
    9209             : 
    9210             : 
    9211       25881 : THREADED_TEST(ExceptionCreateMessageLength) {
    9212           6 :   LocalContext context;
    9213          12 :   v8::HandleScope scope(context->GetIsolate());
    9214             : 
    9215             :   // Test that the message is not truncated.
    9216          12 :   TryCatch try_catch(context->GetIsolate());
    9217             :   CompileRun(
    9218             :       "var message = 'm';"
    9219             :       "while (message.length < 1000) message += message;"
    9220             :       "throw message;");
    9221           6 :   CHECK(try_catch.HasCaught());
    9222             : 
    9223          24 :   CHECK_LT(1000, try_catch.Message()->Get()->Length());
    9224           6 : }
    9225             : 
    9226             : 
    9227           0 : static void YGetter(Local<String> name,
    9228             :                     const v8::PropertyCallbackInfo<v8::Value>& info) {
    9229           0 :   ApiTestFuzzer::Fuzz();
    9230           0 :   info.GetReturnValue().Set(v8_num(10));
    9231           0 : }
    9232             : 
    9233             : 
    9234           6 : static void YSetter(Local<String> name,
    9235             :                     Local<Value> value,
    9236             :                     const v8::PropertyCallbackInfo<void>& info) {
    9237             :   Local<Object> this_obj = Local<Object>::Cast(info.This());
    9238           6 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9239          12 :   if (this_obj->Has(context, name).FromJust())
    9240          12 :     this_obj->Delete(context, name).FromJust();
    9241          12 :   CHECK(this_obj->Set(context, name, value).FromJust());
    9242           6 : }
    9243             : 
    9244             : 
    9245       25881 : THREADED_TEST(DeleteAccessor) {
    9246           6 :   v8::Isolate* isolate = CcTest::isolate();
    9247           6 :   v8::HandleScope scope(isolate);
    9248           6 :   v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
    9249           6 :   obj->SetAccessor(v8_str("y"), YGetter, YSetter);
    9250          12 :   LocalContext context;
    9251             :   v8::Local<v8::Object> holder =
    9252           6 :       obj->NewInstance(context.local()).ToLocalChecked();
    9253          30 :   CHECK(context->Global()
    9254             :             ->Set(context.local(), v8_str("holder"), holder)
    9255             :             .FromJust());
    9256             :   v8::Local<Value> result =
    9257             :       CompileRun("holder.y = 11; holder.y = 12; holder.y");
    9258          18 :   CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
    9259           6 : }
    9260             : 
    9261             : 
    9262             : static int trouble_nesting = 0;
    9263          45 : static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9264          15 :   ApiTestFuzzer::Fuzz();
    9265          15 :   trouble_nesting++;
    9266             : 
    9267             :   // Call a JS function that throws an uncaught exception.
    9268          15 :   Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
    9269          15 :   Local<v8::Object> arg_this = context->Global();
    9270             :   Local<Value> trouble_callee =
    9271          15 :       (trouble_nesting == 3)
    9272          30 :           ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
    9273          60 :           : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
    9274          15 :   CHECK(trouble_callee->IsFunction());
    9275             :   args.GetReturnValue().Set(Function::Cast(*trouble_callee)
    9276          15 :                                 ->Call(context, arg_this, 0, nullptr)
    9277          30 :                                 .FromMaybe(v8::Local<v8::Value>()));
    9278          15 : }
    9279             : 
    9280             : 
    9281             : static int report_count = 0;
    9282           5 : static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
    9283             :                                              v8::Local<Value>) {
    9284           5 :   report_count++;
    9285           5 : }
    9286             : 
    9287             : 
    9288             : // Counts uncaught exceptions, but other tests running in parallel
    9289             : // also have uncaught exceptions.
    9290       25880 : TEST(ApiUncaughtException) {
    9291           5 :   report_count = 0;
    9292           5 :   LocalContext env;
    9293           5 :   v8::Isolate* isolate = env->GetIsolate();
    9294          10 :   v8::HandleScope scope(isolate);
    9295           5 :   isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
    9296             : 
    9297             :   Local<v8::FunctionTemplate> fun =
    9298           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9299           5 :   v8::Local<v8::Object> global = env->Global();
    9300          25 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9301             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9302             :             .FromJust());
    9303             : 
    9304             :   CompileRun(
    9305             :       "function trouble_callee() {"
    9306             :       "  var x = null;"
    9307             :       "  return x.foo;"
    9308             :       "};"
    9309             :       "function trouble_caller() {"
    9310             :       "  trouble();"
    9311             :       "};");
    9312             :   Local<Value> trouble =
    9313          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9314           5 :   CHECK(trouble->IsFunction());
    9315             :   Local<Value> trouble_callee =
    9316          15 :       global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
    9317           5 :   CHECK(trouble_callee->IsFunction());
    9318             :   Local<Value> trouble_caller =
    9319          15 :       global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
    9320           5 :   CHECK(trouble_caller->IsFunction());
    9321             :   Function::Cast(*trouble_caller)
    9322          10 :       ->Call(env.local(), global, 0, nullptr)
    9323           5 :       .FromMaybe(v8::Local<v8::Value>());
    9324           5 :   CHECK_EQ(1, report_count);
    9325          10 :   isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
    9326           5 : }
    9327             : 
    9328             : 
    9329             : static const char* script_resource_name = "ExceptionInNativeScript.js";
    9330           5 : static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
    9331             :                                                 v8::Local<Value>) {
    9332           5 :   v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
    9333          10 :   CHECK(!name_val.IsEmpty() && name_val->IsString());
    9334             :   v8::String::Utf8Value name(v8::Isolate::GetCurrent(),
    9335           5 :                              message->GetScriptOrigin().ResourceName());
    9336           5 :   CHECK_EQ(0, strcmp(script_resource_name, *name));
    9337             :   v8::Local<v8::Context> context =
    9338           5 :       v8::Isolate::GetCurrent()->GetCurrentContext();
    9339          10 :   CHECK_EQ(3, message->GetLineNumber(context).FromJust());
    9340             :   v8::String::Utf8Value source_line(
    9341             :       v8::Isolate::GetCurrent(),
    9342          15 :       message->GetSourceLine(context).ToLocalChecked());
    9343          10 :   CHECK_EQ(0, strcmp("  new o.foo();", *source_line));
    9344           5 : }
    9345             : 
    9346             : 
    9347       25880 : TEST(ExceptionInNativeScript) {
    9348           5 :   LocalContext env;
    9349           5 :   v8::Isolate* isolate = env->GetIsolate();
    9350          10 :   v8::HandleScope scope(isolate);
    9351           5 :   isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
    9352             : 
    9353             :   Local<v8::FunctionTemplate> fun =
    9354           5 :       v8::FunctionTemplate::New(isolate, TroubleCallback);
    9355           5 :   v8::Local<v8::Object> global = env->Global();
    9356          25 :   CHECK(global->Set(env.local(), v8_str("trouble"),
    9357             :                     fun->GetFunction(env.local()).ToLocalChecked())
    9358             :             .FromJust());
    9359             : 
    9360             :   CompileRunWithOrigin(
    9361             :       "function trouble() {\n"
    9362             :       "  var o = {};\n"
    9363             :       "  new o.foo();\n"
    9364             :       "};",
    9365           5 :       script_resource_name);
    9366             :   Local<Value> trouble =
    9367          15 :       global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
    9368           5 :   CHECK(trouble->IsFunction());
    9369          10 :   CHECK(Function::Cast(*trouble)
    9370             :             ->Call(env.local(), global, 0, nullptr)
    9371             :             .IsEmpty());
    9372          10 :   isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
    9373           5 : }
    9374             : 
    9375             : 
    9376       25880 : TEST(CompilationErrorUsingTryCatchHandler) {
    9377           5 :   LocalContext env;
    9378          10 :   v8::HandleScope scope(env->GetIsolate());
    9379          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9380             :   v8_compile("This doesn't &*&@#$&*^ compile.");
    9381          10 :   CHECK(*try_catch.Exception());
    9382          10 :   CHECK(try_catch.HasCaught());
    9383           5 : }
    9384             : 
    9385             : 
    9386       25880 : TEST(TryCatchFinallyUsingTryCatchHandler) {
    9387           5 :   LocalContext env;
    9388          10 :   v8::HandleScope scope(env->GetIsolate());
    9389          10 :   v8::TryCatch try_catch(env->GetIsolate());
    9390             :   CompileRun("try { throw ''; } catch (e) {}");
    9391           5 :   CHECK(!try_catch.HasCaught());
    9392             :   CompileRun("try { throw ''; } finally {}");
    9393           5 :   CHECK(try_catch.HasCaught());
    9394           5 :   try_catch.Reset();
    9395             :   CompileRun(
    9396             :       "(function() {"
    9397             :       "try { throw ''; } finally { return; }"
    9398             :       "})()");
    9399           5 :   CHECK(!try_catch.HasCaught());
    9400             :   CompileRun(
    9401             :       "(function()"
    9402             :       "  { try { throw ''; } finally { throw 0; }"
    9403             :       "})()");
    9404          10 :   CHECK(try_catch.HasCaught());
    9405           5 : }
    9406             : 
    9407             : 
    9408          20 : void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
    9409          10 :   v8::HandleScope scope(args.GetIsolate());
    9410             :   CompileRun(args[0]
    9411          10 :                  ->ToString(args.GetIsolate()->GetCurrentContext())
    9412          20 :                  .ToLocalChecked());
    9413          10 : }
    9414             : 
    9415             : 
    9416       25880 : TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
    9417           5 :   v8::Isolate* isolate = CcTest::isolate();
    9418           5 :   v8::HandleScope scope(isolate);
    9419           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
    9420             :   templ->Set(v8_str("CEvaluate"),
    9421          15 :              v8::FunctionTemplate::New(isolate, CEvaluate));
    9422          10 :   LocalContext context(nullptr, templ);
    9423          10 :   v8::TryCatch try_catch(isolate);
    9424             :   CompileRun("try {"
    9425             :              "  CEvaluate('throw 1;');"
    9426             :              "} finally {"
    9427             :              "}");
    9428           5 :   CHECK(try_catch.HasCaught());
    9429          10 :   CHECK(!try_catch.Message().IsEmpty());
    9430          10 :   String::Utf8Value exception_value(isolate, try_catch.Exception());
    9431           5 :   CHECK_EQ(0, strcmp(*exception_value, "1"));
    9432           5 :   try_catch.Reset();
    9433             :   CompileRun("try {"
    9434             :              "  CEvaluate('throw 1;');"
    9435             :              "} finally {"
    9436             :              "  throw 2;"
    9437             :              "}");
    9438           5 :   CHECK(try_catch.HasCaught());
    9439          10 :   CHECK(!try_catch.Message().IsEmpty());
    9440          10 :   String::Utf8Value finally_exception_value(isolate, try_catch.Exception());
    9441          10 :   CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
    9442           5 : }
    9443             : 
    9444             : 
    9445             : // For use within the TestSecurityHandler() test.
    9446             : static bool g_security_callback_result = false;
    9447          35 : static bool SecurityTestCallback(Local<v8::Context> accessing_context,
    9448             :                                  Local<v8::Object> accessed_object,
    9449             :                                  Local<v8::Value> data) {
    9450             :   printf("a\n");
    9451          35 :   CHECK(!data.IsEmpty() && data->IsInt32());
    9452          70 :   CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
    9453          35 :   return g_security_callback_result;
    9454             : }
    9455             : 
    9456             : 
    9457             : // SecurityHandler can't be run twice
    9458       25880 : TEST(SecurityHandler) {
    9459           5 :   v8::Isolate* isolate = CcTest::isolate();
    9460           5 :   v8::HandleScope scope0(isolate);
    9461             :   v8::Local<v8::ObjectTemplate> global_template =
    9462           5 :       v8::ObjectTemplate::New(isolate);
    9463          10 :   global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
    9464             :   // Create an environment
    9465           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
    9466           5 :   context0->Enter();
    9467             : 
    9468           5 :   v8::Local<v8::Object> global0 = context0->Global();
    9469             :   v8::Local<Script> script0 = v8_compile("foo = 111");
    9470           5 :   script0->Run(context0).ToLocalChecked();
    9471          15 :   CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
    9472             :   v8::Local<Value> foo0 =
    9473          15 :       global0->Get(context0, v8_str("foo")).ToLocalChecked();
    9474          10 :   CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
    9475          15 :   v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
    9476          10 :   CHECK_EQ(999, z0->Int32Value(context0).FromJust());
    9477             : 
    9478             :   // Create another environment, should fail security checks.
    9479          10 :   v8::HandleScope scope1(isolate);
    9480             : 
    9481           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, global_template);
    9482           5 :   context1->Enter();
    9483             : 
    9484           5 :   v8::Local<v8::Object> global1 = context1->Global();
    9485          15 :   global1->Set(context1, v8_str("othercontext"), global0).FromJust();
    9486             :   // This set will fail the security check.
    9487             :   v8::Local<Script> script1 =
    9488             :       v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
    9489          10 :   CHECK(script1->Run(context1).IsEmpty());
    9490           5 :   g_security_callback_result = true;
    9491             :   // This read will pass the security check.
    9492             :   v8::Local<Value> foo1 =
    9493          15 :       global0->Get(context1, v8_str("foo")).ToLocalChecked();
    9494          10 :   CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
    9495             :   // This read will pass the security check.
    9496          15 :   v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
    9497          10 :   CHECK_EQ(999, z1->Int32Value(context1).FromJust());
    9498             : 
    9499             :   // Create another environment, should pass security checks.
    9500             :   {
    9501           5 :     v8::HandleScope scope2(isolate);
    9502          10 :     LocalContext context2;
    9503           5 :     v8::Local<v8::Object> global2 = context2->Global();
    9504          20 :     CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
    9505             :               .FromJust());
    9506             :     v8::Local<Script> script2 =
    9507             :         v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
    9508           5 :     script2->Run(context2.local()).ToLocalChecked();
    9509             :     v8::Local<Value> foo2 =
    9510          15 :         global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
    9511          10 :     CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
    9512             :     v8::Local<Value> z2 =
    9513          15 :         global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
    9514          15 :     CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
    9515             :   }
    9516             : 
    9517           5 :   context1->Exit();
    9518          10 :   context0->Exit();
    9519           5 : }
    9520             : 
    9521             : 
    9522       25881 : THREADED_TEST(SecurityChecks) {
    9523           6 :   LocalContext env1;
    9524          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9525           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9526             : 
    9527           6 :   Local<Value> foo = v8_str("foo");
    9528           6 :   Local<Value> bar = v8_str("bar");
    9529             : 
    9530             :   // Set to the same domain.
    9531           6 :   env1->SetSecurityToken(foo);
    9532             : 
    9533             :   // Create a function in env1.
    9534             :   CompileRun("spy=function(){return spy;}");
    9535             :   Local<Value> spy =
    9536          30 :       env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
    9537           6 :   CHECK(spy->IsFunction());
    9538             : 
    9539             :   // Create another function accessing global objects.
    9540             :   CompileRun("spy2=function(){return new this.Array();}");
    9541             :   Local<Value> spy2 =
    9542          30 :       env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
    9543           6 :   CHECK(spy2->IsFunction());
    9544             : 
    9545             :   // Switch to env2 in the same domain and invoke spy on env2.
    9546             :   {
    9547           6 :     env2->SetSecurityToken(foo);
    9548             :     // Enter env2
    9549             :     Context::Scope scope_env2(env2);
    9550             :     Local<Value> result = Function::Cast(*spy)
    9551          12 :                               ->Call(env2, env2->Global(), 0, nullptr)
    9552           6 :                               .ToLocalChecked();
    9553           6 :     CHECK(result->IsFunction());
    9554             :   }
    9555             : 
    9556             :   {
    9557           6 :     env2->SetSecurityToken(bar);
    9558             :     Context::Scope scope_env2(env2);
    9559             : 
    9560             :     // Call cross_domain_call, it should throw an exception
    9561          12 :     v8::TryCatch try_catch(env1->GetIsolate());
    9562          18 :     CHECK(Function::Cast(*spy2)
    9563             :               ->Call(env2, env2->Global(), 0, nullptr)
    9564             :               .IsEmpty());
    9565           6 :     CHECK(try_catch.HasCaught());
    9566           6 :   }
    9567           6 : }
    9568             : 
    9569             : 
    9570             : // Regression test case for issue 1183439.
    9571       25881 : THREADED_TEST(SecurityChecksForPrototypeChain) {
    9572           6 :   LocalContext current;
    9573          12 :   v8::HandleScope scope(current->GetIsolate());
    9574           6 :   v8::Local<Context> other = Context::New(current->GetIsolate());
    9575             : 
    9576             :   // Change context to be able to get to the Object function in the
    9577             :   // other context without hitting the security checks.
    9578             :   v8::Local<Value> other_object;
    9579             :   { Context::Scope scope(other);
    9580             :     other_object =
    9581          24 :         other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
    9582          18 :     CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
    9583             :   }
    9584             : 
    9585          36 :   CHECK(current->Global()
    9586             :             ->Set(current.local(), v8_str("other"), other->Global())
    9587             :             .FromJust());
    9588          30 :   CHECK(v8_compile("other")
    9589             :             ->Run(current.local())
    9590             :             .ToLocalChecked()
    9591             :             ->Equals(current.local(), other->Global())
    9592             :             .FromJust());
    9593             : 
    9594             :   // Make sure the security check fails here and we get an undefined
    9595             :   // result instead of getting the Object function. Repeat in a loop
    9596             :   // to make sure to exercise the IC code.
    9597             :   v8::Local<Script> access_other0 = v8_compile("other.Object");
    9598             :   v8::Local<Script> access_other1 = v8_compile("other[42]");
    9599          36 :   for (int i = 0; i < 5; i++) {
    9600          60 :     CHECK(access_other0->Run(current.local()).IsEmpty());
    9601          60 :     CHECK(access_other1->Run(current.local()).IsEmpty());
    9602             :   }
    9603             : 
    9604             :   // Create an object that has 'other' in its prototype chain and make
    9605             :   // sure we cannot access the Object function indirectly through
    9606             :   // that. Repeat in a loop to make sure to exercise the IC code.
    9607             :   v8_compile(
    9608             :       "function F() { };"
    9609             :       "F.prototype = other;"
    9610             :       "var f = new F();")
    9611           6 :       ->Run(current.local())
    9612           6 :       .ToLocalChecked();
    9613             :   v8::Local<Script> access_f0 = v8_compile("f.Object");
    9614             :   v8::Local<Script> access_f1 = v8_compile("f[42]");
    9615          36 :   for (int j = 0; j < 5; j++) {
    9616          60 :     CHECK(access_f0->Run(current.local()).IsEmpty());
    9617          60 :     CHECK(access_f1->Run(current.local()).IsEmpty());
    9618             :   }
    9619             : 
    9620             :   // Now it gets hairy: Set the prototype for the other global object
    9621             :   // to be the current global object. The prototype chain for 'f' now
    9622             :   // goes through 'other' but ends up in the current global object.
    9623             :   { Context::Scope scope(other);
    9624          30 :     CHECK(other->Global()
    9625             :               ->Set(other, v8_str("__proto__"), current->Global())
    9626             :               .FromJust());
    9627             :   }
    9628             :   // Set a named and an index property on the current global
    9629             :   // object. To force the lookup to go through the other global object,
    9630             :   // the properties must not exist in the other global object.
    9631          30 :   CHECK(current->Global()
    9632             :             ->Set(current.local(), v8_str("foo"), v8_num(100))
    9633             :             .FromJust());
    9634          24 :   CHECK(current->Global()
    9635             :             ->Set(current.local(), v8_num(99), v8_num(101))
    9636             :             .FromJust());
    9637             :   // Try to read the properties from f and make sure that the access
    9638             :   // gets stopped by the security checks on the other global object.
    9639             :   Local<Script> access_f2 = v8_compile("f.foo");
    9640             :   Local<Script> access_f3 = v8_compile("f[99]");
    9641          36 :   for (int k = 0; k < 5; k++) {
    9642          60 :     CHECK(access_f2->Run(current.local()).IsEmpty());
    9643          60 :     CHECK(access_f3->Run(current.local()).IsEmpty());
    9644           6 :   }
    9645           6 : }
    9646             : 
    9647             : 
    9648             : static bool security_check_with_gc_called;
    9649             : 
    9650          10 : static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
    9651             :                                        Local<v8::Object> accessed_object,
    9652             :                                        Local<v8::Value> data) {
    9653          10 :   CcTest::CollectAllGarbage();
    9654          10 :   security_check_with_gc_called = true;
    9655          10 :   return true;
    9656             : }
    9657             : 
    9658             : 
    9659       25880 : TEST(SecurityTestGCAllowed) {
    9660           5 :   v8::Isolate* isolate = CcTest::isolate();
    9661           5 :   v8::HandleScope handle_scope(isolate);
    9662             :   v8::Local<v8::ObjectTemplate> object_template =
    9663           5 :       v8::ObjectTemplate::New(isolate);
    9664           5 :   object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
    9665             : 
    9666           5 :   v8::Local<Context> context = Context::New(isolate);
    9667             :   v8::Context::Scope context_scope(context);
    9668             : 
    9669          25 :   CHECK(context->Global()
    9670             :             ->Set(context, v8_str("obj"),
    9671             :                   object_template->NewInstance(context).ToLocalChecked())
    9672             :             .FromJust());
    9673             : 
    9674           5 :   security_check_with_gc_called = false;
    9675             :   CompileRun("obj[0] = new String(1002);");
    9676           5 :   CHECK(security_check_with_gc_called);
    9677             : 
    9678           5 :   security_check_with_gc_called = false;
    9679          20 :   CHECK(CompileRun("obj[0]")
    9680             :             ->ToString(context)
    9681             :             .ToLocalChecked()
    9682             :             ->Equals(context, v8_str("1002"))
    9683             :             .FromJust());
    9684          10 :   CHECK(security_check_with_gc_called);
    9685           5 : }
    9686             : 
    9687             : 
    9688       25881 : THREADED_TEST(CrossDomainDelete) {
    9689           6 :   LocalContext env1;
    9690          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9691           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9692             : 
    9693           6 :   Local<Value> foo = v8_str("foo");
    9694           6 :   Local<Value> bar = v8_str("bar");
    9695             : 
    9696             :   // Set to the same domain.
    9697           6 :   env1->SetSecurityToken(foo);
    9698           6 :   env2->SetSecurityToken(foo);
    9699             : 
    9700          30 :   CHECK(
    9701             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9702          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9703             : 
    9704             :   // Change env2 to a different domain and delete env1.prop.
    9705           6 :   env2->SetSecurityToken(bar);
    9706             :   {
    9707             :     Context::Scope scope_env2(env2);
    9708             :     Local<Value> result =
    9709             :         CompileRun("delete env1.prop");
    9710           6 :     CHECK(result.IsEmpty());
    9711             :   }
    9712             : 
    9713             :   // Check that env1.prop still exists.
    9714             :   Local<Value> v =
    9715          30 :       env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
    9716           6 :   CHECK(v->IsNumber());
    9717          18 :   CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
    9718           6 : }
    9719             : 
    9720             : 
    9721       25881 : THREADED_TEST(CrossDomainPropertyIsEnumerable) {
    9722           6 :   LocalContext env1;
    9723          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9724           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9725             : 
    9726           6 :   Local<Value> foo = v8_str("foo");
    9727           6 :   Local<Value> bar = v8_str("bar");
    9728             : 
    9729             :   // Set to the same domain.
    9730           6 :   env1->SetSecurityToken(foo);
    9731           6 :   env2->SetSecurityToken(foo);
    9732             : 
    9733          30 :   CHECK(
    9734             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9735          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9736             : 
    9737             :   // env1.prop is enumerable in env2.
    9738           6 :   Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
    9739             :   {
    9740             :     Context::Scope scope_env2(env2);
    9741           6 :     Local<Value> result = CompileRun(test);
    9742           6 :     CHECK(result->IsTrue());
    9743             :   }
    9744             : 
    9745             :   // Change env2 to a different domain and test again.
    9746           6 :   env2->SetSecurityToken(bar);
    9747             :   {
    9748             :     Context::Scope scope_env2(env2);
    9749           6 :     Local<Value> result = CompileRun(test);
    9750           6 :     CHECK(result.IsEmpty());
    9751           6 :   }
    9752           6 : }
    9753             : 
    9754             : 
    9755       25881 : THREADED_TEST(CrossDomainFor) {
    9756           6 :   LocalContext env1;
    9757          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9758           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9759             : 
    9760           6 :   Local<Value> foo = v8_str("foo");
    9761           6 :   Local<Value> bar = v8_str("bar");
    9762             : 
    9763             :   // Set to the same domain.
    9764           6 :   env1->SetSecurityToken(foo);
    9765           6 :   env2->SetSecurityToken(foo);
    9766             : 
    9767          30 :   CHECK(
    9768             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9769          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9770             : 
    9771             :   // Change env2 to a different domain and set env1's global object
    9772             :   // as the __proto__ of an object in env2 and enumerate properties
    9773             :   // in for-in. It shouldn't enumerate properties on env1's global
    9774             :   // object. It shouldn't throw either, just silently ignore them.
    9775           6 :   env2->SetSecurityToken(bar);
    9776             :   {
    9777             :     Context::Scope scope_env2(env2);
    9778             :     Local<Value> result = CompileRun(
    9779             :         "(function() {"
    9780             :         "  try {"
    9781             :         "    for (var p in env1) {"
    9782             :         "      if (p == 'prop') return false;"
    9783             :         "    }"
    9784             :         "    return true;"
    9785             :         "  } catch (e) {"
    9786             :         "    return false;"
    9787             :         "  }"
    9788             :         "})()");
    9789           6 :     CHECK(result->IsTrue());
    9790           6 :   }
    9791           6 : }
    9792             : 
    9793             : 
    9794       25881 : THREADED_TEST(CrossDomainForInOnPrototype) {
    9795           6 :   LocalContext env1;
    9796          12 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9797           6 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9798             : 
    9799           6 :   Local<Value> foo = v8_str("foo");
    9800           6 :   Local<Value> bar = v8_str("bar");
    9801             : 
    9802             :   // Set to the same domain.
    9803           6 :   env1->SetSecurityToken(foo);
    9804           6 :   env2->SetSecurityToken(foo);
    9805             : 
    9806          30 :   CHECK(
    9807             :       env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
    9808          30 :   CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
    9809             : 
    9810             :   // Change env2 to a different domain and set env1's global object
    9811             :   // as the __proto__ of an object in env2 and enumerate properties
    9812             :   // in for-in. It shouldn't enumerate properties on env1's global
    9813             :   // object.
    9814           6 :   env2->SetSecurityToken(bar);
    9815             :   {
    9816             :     Context::Scope scope_env2(env2);
    9817             :     Local<Value> result = CompileRun(
    9818             :         "(function() {"
    9819             :         "  var obj = { '__proto__': env1 };"
    9820             :         "  try {"
    9821             :         "    for (var p in obj) {"
    9822             :         "      if (p == 'prop') return false;"
    9823             :         "    }"
    9824             :         "    return true;"
    9825             :         "  } catch (e) {"
    9826             :         "    return false;"
    9827             :         "  }"
    9828             :         "})()");
    9829           6 :     CHECK(result->IsTrue());
    9830           6 :   }
    9831           6 : }
    9832             : 
    9833             : 
    9834       25880 : TEST(ContextDetachGlobal) {
    9835           5 :   LocalContext env1;
    9836          10 :   v8::HandleScope handle_scope(env1->GetIsolate());
    9837           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9838             : 
    9839             : 
    9840           5 :   Local<Value> foo = v8_str("foo");
    9841             : 
    9842             :   // Set to the same domain.
    9843           5 :   env1->SetSecurityToken(foo);
    9844           5 :   env2->SetSecurityToken(foo);
    9845             : 
    9846             :   // Enter env2
    9847           5 :   env2->Enter();
    9848             : 
    9849             :   // Create a function in env2 and add a reference to it in env1.
    9850           5 :   Local<v8::Object> global2 = env2->Global();
    9851          20 :   CHECK(global2->Set(env2, v8_str("prop"),
    9852             :                      v8::Integer::New(env2->GetIsolate(), 1))
    9853             :             .FromJust());
    9854             :   CompileRun("function getProp() {return prop;}");
    9855             : 
    9856          35 :   CHECK(env1->Global()
    9857             :             ->Set(env1.local(), v8_str("getProp"),
    9858             :                   global2->Get(env2, v8_str("getProp")).ToLocalChecked())
    9859             :             .FromJust());
    9860             : 
    9861             :   // Detach env2's global, and reuse the global object of env2
    9862           5 :   env2->Exit();
    9863           5 :   env2->DetachGlobal();
    9864             : 
    9865             :   v8::Local<Context> env3 = Context::New(
    9866           5 :       env1->GetIsolate(), nullptr, v8::Local<v8::ObjectTemplate>(), global2);
    9867          10 :   env3->SetSecurityToken(v8_str("bar"));
    9868             : 
    9869           5 :   env3->Enter();
    9870           5 :   Local<v8::Object> global3 = env3->Global();
    9871          10 :   CHECK(global2->Equals(env3, global3).FromJust());
    9872          15 :   CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
    9873          15 :   CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
    9874          20 :   CHECK(global3->Set(env3, v8_str("prop"),
    9875             :                      v8::Integer::New(env3->GetIsolate(), -1))
    9876             :             .FromJust());
    9877          20 :   CHECK(global3->Set(env3, v8_str("prop2"),
    9878             :                      v8::Integer::New(env3->GetIsolate(), 2))
    9879             :             .FromJust());
    9880           5 :   env3->Exit();
    9881             : 
    9882             :   // Call getProp in env1, and it should return the value 1
    9883             :   {
    9884           5 :     Local<v8::Object> global1 = env1->Global();
    9885             :     Local<Value> get_prop =
    9886          20 :         global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
    9887           5 :     CHECK(get_prop->IsFunction());
    9888           5 :     v8::TryCatch try_catch(env1->GetIsolate());
    9889             :     Local<Value> r = Function::Cast(*get_prop)
    9890          10 :                          ->Call(env1.local(), global1, 0, nullptr)
    9891           5 :                          .ToLocalChecked();
    9892           5 :     CHECK(!try_catch.HasCaught());
    9893          10 :     CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
    9894             :   }
    9895             : 
    9896             :   // Check that env3 is not accessible from env1
    9897             :   {
    9898          10 :     v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
    9899           5 :     CHECK(r.IsEmpty());
    9900           5 :   }
    9901           5 : }
    9902             : 
    9903             : 
    9904       25880 : TEST(DetachGlobal) {
    9905           5 :   LocalContext env1;
    9906          10 :   v8::HandleScope scope(env1->GetIsolate());
    9907             : 
    9908             :   // Create second environment.
    9909           5 :   v8::Local<Context> env2 = Context::New(env1->GetIsolate());
    9910             : 
    9911           5 :   Local<Value> foo = v8_str("foo");
    9912             : 
    9913             :   // Set same security token for env1 and env2.
    9914           5 :   env1->SetSecurityToken(foo);
    9915           5 :   env2->SetSecurityToken(foo);
    9916             : 
    9917             :   // Create a property on the global object in env2.
    9918             :   {
    9919             :     v8::Context::Scope scope(env2);
    9920          25 :     CHECK(env2->Global()
    9921             :               ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
    9922             :               .FromJust());
    9923             :   }
    9924             : 
    9925             :   // Create a reference to env2 global from env1 global.
    9926          30 :   CHECK(env1->Global()
    9927             :             ->Set(env1.local(), v8_str("other"), env2->Global())
    9928             :             .FromJust());
    9929             : 
    9930             :   // Check that we have access to other.p in env2 from env1.
    9931             :   Local<Value> result = CompileRun("other.p");
    9932           5 :   CHECK(result->IsInt32());
    9933          10 :   CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
    9934             : 
    9935             :   // Hold on to global from env2 and detach global from env2.
    9936           5 :   Local<v8::Object> global2 = env2->Global();
    9937           5 :   env2->DetachGlobal();
    9938             : 
    9939             :   // Check that the global has been detached. No other.p property can
    9940             :   // be found.
    9941             :   result = CompileRun("other.p");
    9942           5 :   CHECK(result.IsEmpty());
    9943             : 
    9944             :   // Reuse global2 for env3.
    9945             :   v8::Local<Context> env3 = Context::New(
    9946           5 :       env1->GetIsolate(), nullptr, v8::Local<v8::ObjectTemplate>(), global2);
    9947          15 :   CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
    9948             : 
    9949             :   // Start by using the same security token for env3 as for env1 and env2.
    9950           5 :   env3->SetSecurityToken(foo);
    9951             : 
    9952             :   // Create a property on the global object in env3.
    9953             :   {
    9954             :     v8::Context::Scope scope(env3);
    9955          25 :     CHECK(env3->Global()
    9956             :               ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
    9957             :               .FromJust());
    9958             :   }
    9959             : 
    9960             :   // Check that other.p is now the property in env3 and that we have access.
    9961             :   result = CompileRun("other.p");
    9962           5 :   CHECK(result->IsInt32());
    9963          15 :   CHECK_EQ(24, result->Int32Value(env3).FromJust());
    9964           5 : }
    9965             : 
    9966             : 
    9967         130 : void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
    9968          65 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
    9969             :   info.GetReturnValue().Set(
    9970         260 :       context->Global()->Get(context, v8_str("x")).ToLocalChecked());
    9971          65 : }
    9972             : 
    9973             : 
    9974       25880 : TEST(DetachedAccesses) {
    9975           5 :   LocalContext env1;
    9976          10 :   v8::HandleScope scope(env1->GetIsolate());
    9977             : 
    9978             :   // Create second environment.
    9979             :   Local<ObjectTemplate> inner_global_template =
    9980          10 :       FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
    9981             :   inner_global_template ->SetAccessorProperty(
    9982          10 :       v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
    9983             :   v8::Local<Context> env2 =
    9984           5 :       Context::New(env1->GetIsolate(), nullptr, inner_global_template);
    9985             : 
    9986           5 :   Local<Value> foo = v8_str("foo");
    9987             : 
    9988             :   // Set same security token for env1 and env2.
    9989           5 :   env1->SetSecurityToken(foo);
    9990           5 :   env2->SetSecurityToken(foo);
    9991             : 
    9992          30 :   CHECK(env1->Global()
    9993             :             ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
    9994             :             .FromJust());
    9995             : 
    9996             :   {
    9997             :     v8::Context::Scope scope(env2);
    9998          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
    9999             :     CompileRun(
   10000             :         "function bound_x() { return x; }"
   10001             :         "function get_x()   { return this.x; }"
   10002             :         "function get_x_w() { return (function() {return this.x;})(); }");
   10003          25 :     CHECK(env1->Global()
   10004             :               ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
   10005             :               .FromJust());
   10006          25 :     CHECK(env1->Global()
   10007             :               ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
   10008             :               .FromJust());
   10009          25 :     CHECK(env1->Global()
   10010             :               ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
   10011             :               .FromJust());
   10012             :     env1->Global()
   10013             :         ->Set(env1.local(), v8_str("this_x"),
   10014          20 :               CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
   10015          10 :         .FromJust();
   10016             :   }
   10017             : 
   10018           5 :   Local<Object> env2_global = env2->Global();
   10019           5 :   env2->DetachGlobal();
   10020             : 
   10021             :   Local<Value> result;
   10022             :   result = CompileRun("bound_x()");
   10023          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   10024             :   result = CompileRun("get_x()");
   10025           5 :   CHECK(result.IsEmpty());
   10026             :   result = CompileRun("get_x_w()");
   10027           5 :   CHECK(result.IsEmpty());
   10028             :   result = CompileRun("this_x()");
   10029          15 :   CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
   10030             : 
   10031             :   // Reattach env2's proxy
   10032             :   env2 = Context::New(env1->GetIsolate(), nullptr,
   10033           5 :                       v8::Local<v8::ObjectTemplate>(), env2_global);
   10034           5 :   env2->SetSecurityToken(foo);
   10035             :   {
   10036             :     v8::Context::Scope scope(env2);
   10037          25 :     CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
   10038          25 :     CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
   10039             :     result = CompileRun(
   10040             :         "results = [];"
   10041             :         "for (var i = 0; i < 4; i++ ) {"
   10042             :         "  results.push(env1.bound_x());"
   10043             :         "  results.push(env1.get_x());"
   10044             :         "  results.push(env1.get_x_w());"
   10045             :         "  results.push(env1.this_x());"
   10046             :         "}"
   10047             :         "results");
   10048             :     Local<v8::Array> results = Local<v8::Array>::Cast(result);
   10049           5 :     CHECK_EQ(16u, results->Length());
   10050          20 :     for (int i = 0; i < 16; i += 4) {
   10051          80 :       CHECK(v8_str("env2_x")
   10052             :                 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
   10053             :                 .FromJust());
   10054          80 :       CHECK(v8_str("env1_x")
   10055             :                 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
   10056             :                 .FromJust());
   10057          80 :       CHECK(v8_str("env3_x")
   10058             :                 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
   10059             :                 .FromJust());
   10060          80 :       CHECK(v8_str("env2_x")
   10061             :                 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
   10062             :                 .FromJust());
   10063             :     }
   10064             :   }
   10065             : 
   10066             :   result = CompileRun(
   10067             :       "results = [];"
   10068             :       "for (var i = 0; i < 4; i++ ) {"
   10069             :       "  results.push(bound_x());"
   10070             :       "  results.push(get_x());"
   10071             :       "  results.push(get_x_w());"
   10072             :       "  results.push(this_x());"
   10073             :       "}"
   10074             :       "results");
   10075             :   Local<v8::Array> results = Local<v8::Array>::Cast(result);
   10076           5 :   CHECK_EQ(16u, results->Length());
   10077          20 :   for (int i = 0; i < 16; i += 4) {
   10078          80 :     CHECK(v8_str("env2_x")
   10079             :               ->Equals(env1.local(),
   10080             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
   10081             :               .FromJust());
   10082          80 :     CHECK(v8_str("env3_x")
   10083             :               ->Equals(env1.local(),
   10084             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
   10085             :               .FromJust());
   10086          80 :     CHECK(v8_str("env3_x")
   10087             :               ->Equals(env1.local(),
   10088             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
   10089             :               .FromJust());
   10090          80 :     CHECK(v8_str("env2_x")
   10091             :               ->Equals(env1.local(),
   10092             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
   10093             :               .FromJust());
   10094             :   }
   10095             : 
   10096             :   result = CompileRun(
   10097             :       "results = [];"
   10098             :       "for (var i = 0; i < 4; i++ ) {"
   10099             :       "  results.push(this.bound_x());"
   10100             :       "  results.push(this.get_x());"
   10101             :       "  results.push(this.get_x_w());"
   10102             :       "  results.push(this.this_x());"
   10103             :       "}"
   10104             :       "results");
   10105             :   results = Local<v8::Array>::Cast(result);
   10106           5 :   CHECK_EQ(16u, results->Length());
   10107          20 :   for (int i = 0; i < 16; i += 4) {
   10108          80 :     CHECK(v8_str("env2_x")
   10109             :               ->Equals(env1.local(),
   10110             :                        results->Get(env1.local(), i + 0).ToLocalChecked())
   10111             :               .FromJust());
   10112          80 :     CHECK(v8_str("env1_x")
   10113             :               ->Equals(env1.local(),
   10114             :                        results->Get(env1.local(), i + 1).ToLocalChecked())
   10115             :               .FromJust());
   10116          80 :     CHECK(v8_str("env3_x")
   10117             :               ->Equals(env1.local(),
   10118             :                        results->Get(env1.local(), i + 2).ToLocalChecked())
   10119             :               .FromJust());
   10120          80 :     CHECK(v8_str("env2_x")
   10121             :               ->Equals(env1.local(),
   10122             :                        results->Get(env1.local(), i + 3).ToLocalChecked())
   10123             :               .FromJust());
   10124           5 :   }
   10125           5 : }
   10126             : 
   10127             : 
   10128             : static bool allowed_access = false;
   10129         370 : static bool AccessBlocker(Local<v8::Context> accessing_context,
   10130             :                           Local<v8::Object> accessed_object,
   10131             :                           Local<v8::Value> data) {
   10132         370 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   10133        1110 :   return context->Global()->Equals(context, accessed_object).FromJust() ||
   10134         370 :          allowed_access;
   10135             : }
   10136             : 
   10137             : 
   10138             : static int g_echo_value = -1;
   10139             : 
   10140             : 
   10141          15 : static void EchoGetter(
   10142             :     Local<String> name,
   10143             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10144          15 :   info.GetReturnValue().Set(v8_num(g_echo_value));
   10145          15 : }
   10146             : 
   10147             : 
   10148          10 : static void EchoSetter(Local<String> name, Local<Value> value,
   10149             :                        const v8::PropertyCallbackInfo<void>& args) {
   10150          10 :   if (value->IsNumber())
   10151             :     g_echo_value =
   10152          20 :         value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   10153          10 : }
   10154             : 
   10155             : 
   10156           0 : static void UnreachableGetter(
   10157             :     Local<String> name,
   10158             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   10159           0 :   UNREACHABLE();  // This function should not be called..
   10160             : }
   10161             : 
   10162             : 
   10163           0 : static void UnreachableSetter(Local<String>,
   10164             :                               Local<Value>,
   10165             :                               const v8::PropertyCallbackInfo<void>&) {
   10166           0 :   UNREACHABLE();  // This function should not be called.
   10167             : }
   10168             : 
   10169             : 
   10170           0 : static void UnreachableFunction(
   10171             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   10172           0 :   UNREACHABLE();  // This function should not be called..
   10173             : }
   10174             : 
   10175             : 
   10176       25880 : TEST(AccessControl) {
   10177           5 :   v8::Isolate* isolate = CcTest::isolate();
   10178           5 :   v8::HandleScope handle_scope(isolate);
   10179             :   v8::Local<v8::ObjectTemplate> global_template =
   10180           5 :       v8::ObjectTemplate::New(isolate);
   10181             : 
   10182           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10183             : 
   10184             :   // Add an accessor accessible by cross-domain JS code.
   10185             :   global_template->SetAccessor(
   10186             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10187           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10188             : 
   10189             : 
   10190             :   // Add an accessor that is not accessible by cross-domain JS code.
   10191             :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10192             :                                UnreachableSetter, v8::Local<Value>(),
   10193           5 :                                v8::DEFAULT);
   10194             : 
   10195             :   global_template->SetAccessorProperty(
   10196             :       v8_str("blocked_js_prop"),
   10197             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   10198             :       v8::FunctionTemplate::New(isolate, UnreachableFunction),
   10199             :       v8::None,
   10200          15 :       v8::DEFAULT);
   10201             : 
   10202             :   // Create an environment
   10203           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10204           5 :   context0->Enter();
   10205             : 
   10206           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10207             : 
   10208             :   // Define a property with JS getter and setter.
   10209             :   CompileRun(
   10210             :       "function getter() { return 'getter'; };\n"
   10211             :       "function setter() { return 'setter'; }\n"
   10212             :       "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
   10213             : 
   10214             :   Local<Value> getter =
   10215          15 :       global0->Get(context0, v8_str("getter")).ToLocalChecked();
   10216             :   Local<Value> setter =
   10217          15 :       global0->Get(context0, v8_str("setter")).ToLocalChecked();
   10218             : 
   10219             :   // And define normal element.
   10220          15 :   CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
   10221             : 
   10222             :   // Define an element with JS getter and setter.
   10223             :   CompileRun(
   10224             :       "function el_getter() { return 'el_getter'; };\n"
   10225             :       "function el_setter() { return 'el_setter'; };\n"
   10226             :       "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
   10227             : 
   10228             :   Local<Value> el_getter =
   10229          15 :       global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
   10230             :   Local<Value> el_setter =
   10231          15 :       global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
   10232             : 
   10233          10 :   v8::HandleScope scope1(isolate);
   10234             : 
   10235           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10236           5 :   context1->Enter();
   10237             : 
   10238           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10239          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10240             : 
   10241             :   // Access blocked property.
   10242             :   CompileRun("other.blocked_prop = 1");
   10243             : 
   10244           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10245           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10246             :             .IsEmpty());
   10247           5 :   CHECK(
   10248             :       CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
   10249             : 
   10250             :   // Access blocked element.
   10251           5 :   CHECK(CompileRun("other[239] = 1").IsEmpty());
   10252             : 
   10253           5 :   CHECK(CompileRun("other[239]").IsEmpty());
   10254           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
   10255           5 :   CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
   10256             : 
   10257           5 :   allowed_access = true;
   10258             :   // Now we can enumerate the property.
   10259             :   ExpectTrue("propertyIsEnumerable.call(other, '239')");
   10260           5 :   allowed_access = false;
   10261             : 
   10262             :   // Access a property with JS accessor.
   10263           5 :   CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
   10264             : 
   10265           5 :   CHECK(CompileRun("other.js_accessor_p").IsEmpty());
   10266           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
   10267             :             .IsEmpty());
   10268             : 
   10269           5 :   allowed_access = true;
   10270             : 
   10271           5 :   ExpectString("other.js_accessor_p", "getter");
   10272             :   ExpectObject(
   10273           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
   10274             :   ExpectObject(
   10275           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
   10276             :   ExpectUndefined(
   10277           5 :       "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
   10278             : 
   10279           5 :   allowed_access = false;
   10280             : 
   10281             :   // Access an element with JS accessor.
   10282           5 :   CHECK(CompileRun("other[42] = 2").IsEmpty());
   10283             : 
   10284           5 :   CHECK(CompileRun("other[42]").IsEmpty());
   10285           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
   10286             : 
   10287           5 :   allowed_access = true;
   10288             : 
   10289           5 :   ExpectString("other[42]", "el_getter");
   10290           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
   10291           5 :   ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
   10292           5 :   ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
   10293             : 
   10294           5 :   allowed_access = false;
   10295             : 
   10296             :   v8::Local<Value> value;
   10297             : 
   10298             :   // Access accessible property
   10299             :   value = CompileRun("other.accessible_prop = 3");
   10300           5 :   CHECK(value->IsNumber());
   10301          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10302           5 :   CHECK_EQ(3, g_echo_value);
   10303             : 
   10304             :   value = CompileRun("other.accessible_prop");
   10305           5 :   CHECK(value->IsNumber());
   10306          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10307             : 
   10308             :   value = CompileRun(
   10309             :       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   10310           5 :   CHECK(value->IsNumber());
   10311          10 :   CHECK_EQ(3, value->Int32Value(context1).FromJust());
   10312             : 
   10313             :   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   10314           5 :   CHECK(value->IsTrue());
   10315             : 
   10316             :   // Enumeration doesn't enumerate accessors from inaccessible objects in
   10317             :   // the prototype chain even if the accessors are in themselves accessible.
   10318             :   // Enumeration doesn't throw, it silently ignores what it can't access.
   10319             :   value = CompileRun(
   10320             :       "(function() {"
   10321             :       "  var obj = { '__proto__': other };"
   10322             :       "  try {"
   10323             :       "    for (var p in obj) {"
   10324             :       "      if (p == 'accessible_prop' ||"
   10325             :       "          p == 'blocked_js_prop' ||"
   10326             :       "          p == 'blocked_js_prop') {"
   10327             :       "        return false;"
   10328             :       "      }"
   10329             :       "    }"
   10330             :       "    return true;"
   10331             :       "  } catch (e) {"
   10332             :       "    return false;"
   10333             :       "  }"
   10334             :       "})()");
   10335           5 :   CHECK(value->IsTrue());
   10336             : 
   10337             :   // Test that preventExtensions fails on a non-accessible object even if that
   10338             :   // object is already non-extensible.
   10339          20 :   CHECK(global1->Set(context1, v8_str("checked_object"),
   10340             :                      global_template->NewInstance(context1).ToLocalChecked())
   10341             :             .FromJust());
   10342           5 :   allowed_access = true;
   10343             :   CompileRun("Object.preventExtensions(checked_object)");
   10344             :   ExpectFalse("Object.isExtensible(checked_object)");
   10345           5 :   allowed_access = false;
   10346           5 :   CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
   10347             : 
   10348           5 :   context1->Exit();
   10349          10 :   context0->Exit();
   10350           5 : }
   10351             : 
   10352             : 
   10353       25880 : TEST(AccessControlES5) {
   10354           5 :   v8::Isolate* isolate = CcTest::isolate();
   10355           5 :   v8::HandleScope handle_scope(isolate);
   10356             :   v8::Local<v8::ObjectTemplate> global_template =
   10357           5 :       v8::ObjectTemplate::New(isolate);
   10358             : 
   10359           5 :   global_template->SetAccessCheckCallback(AccessBlocker);
   10360             : 
   10361             :   // Add accessible accessor.
   10362             :   global_template->SetAccessor(
   10363             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10364           5 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10365             : 
   10366             : 
   10367             :   // Add an accessor that is not accessible by cross-domain JS code.
   10368             :   global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
   10369             :                                UnreachableSetter, v8::Local<Value>(),
   10370           5 :                                v8::DEFAULT);
   10371             : 
   10372             :   // Create an environment
   10373           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10374           5 :   context0->Enter();
   10375             : 
   10376           5 :   v8::Local<v8::Object> global0 = context0->Global();
   10377             : 
   10378           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10379           5 :   context1->Enter();
   10380           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10381          15 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10382             : 
   10383             :   // Regression test for issue 1154.
   10384           5 :   CHECK(CompileRun("Object.keys(other).length == 1")->BooleanValue(isolate));
   10385           5 :   CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
   10386             :             ->BooleanValue(isolate));
   10387           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10388             : 
   10389             :   // Regression test for issue 1027.
   10390             :   CompileRun("Object.defineProperty(\n"
   10391             :              "  other, 'blocked_prop', {configurable: false})");
   10392           5 :   CHECK(CompileRun("other.blocked_prop").IsEmpty());
   10393           5 :   CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
   10394             :             .IsEmpty());
   10395             : 
   10396             :   // Regression test for issue 1171.
   10397             :   ExpectTrue("Object.isExtensible(other)");
   10398             :   CompileRun("Object.preventExtensions(other)");
   10399             :   ExpectTrue("Object.isExtensible(other)");
   10400             : 
   10401             :   // Object.seal and Object.freeze.
   10402             :   CompileRun("Object.freeze(other)");
   10403             :   ExpectTrue("Object.isExtensible(other)");
   10404             : 
   10405             :   CompileRun("Object.seal(other)");
   10406             :   ExpectTrue("Object.isExtensible(other)");
   10407             : 
   10408             :   // Regression test for issue 1250.
   10409             :   // Make sure that we can set the accessible accessors value using normal
   10410             :   // assignment.
   10411             :   CompileRun("other.accessible_prop = 42");
   10412           5 :   CHECK_EQ(42, g_echo_value);
   10413             : 
   10414             :   // [[DefineOwnProperty]] always throws for access-checked objects.
   10415           5 :   CHECK(
   10416             :       CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
   10417             :           .IsEmpty());
   10418           5 :   CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
   10419           5 :   CHECK_EQ(42, g_echo_value);  // Make sure we didn't call the setter.
   10420           5 : }
   10421             : 
   10422         229 : static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
   10423             :                                 Local<v8::Object> global,
   10424             :                                 Local<v8::Value> data) {
   10425         229 :   i::PrintF("Access blocked.\n");
   10426         229 :   return false;
   10427             : }
   10428             : 
   10429           5 : static bool AccessAlwaysAllowed(Local<v8::Context> accessing_context,
   10430             :                                 Local<v8::Object> global,
   10431             :                                 Local<v8::Value> data) {
   10432           5 :   i::PrintF("Access allowed.\n");
   10433           5 :   return true;
   10434             : }
   10435             : 
   10436       25881 : THREADED_TEST(AccessControlGetOwnPropertyNames) {
   10437           6 :   v8::Isolate* isolate = CcTest::isolate();
   10438           6 :   v8::HandleScope handle_scope(isolate);
   10439           6 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10440             : 
   10441          18 :   obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   10442           6 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10443             : 
   10444             :   // Add an accessor accessible by cross-domain JS code.
   10445             :   obj_template->SetAccessor(
   10446             :       v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
   10447           6 :       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
   10448             : 
   10449             :   // Create an environment
   10450           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   10451           6 :   context0->Enter();
   10452             : 
   10453           6 :   v8::Local<v8::Object> global0 = context0->Global();
   10454             : 
   10455          12 :   v8::HandleScope scope1(CcTest::isolate());
   10456             : 
   10457           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10458           6 :   context1->Enter();
   10459             : 
   10460           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10461          18 :   CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
   10462          24 :   CHECK(global1->Set(context1, v8_str("object"),
   10463             :                      obj_template->NewInstance(context1).ToLocalChecked())
   10464             :             .FromJust());
   10465             : 
   10466             :   v8::Local<Value> value;
   10467             : 
   10468             :   // Attempt to get the property names of the other global object and
   10469             :   // of an object that requires access checks.  Accessing the other
   10470             :   // global object should be blocked by access checks on the global
   10471             :   // proxy object.  Accessing the object that requires access checks
   10472             :   // is blocked by the access checks on the object itself.
   10473             :   value = CompileRun(
   10474             :       "var names = Object.getOwnPropertyNames(other);"
   10475             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10476           6 :   CHECK(value->BooleanValue(isolate));
   10477             : 
   10478             :   value = CompileRun(
   10479             :       "var names = Object.getOwnPropertyNames(object);"
   10480             :       "names.length == 1 && names[0] == 'accessible_prop';");
   10481           6 :   CHECK(value->BooleanValue(isolate));
   10482             : 
   10483           6 :   context1->Exit();
   10484          12 :   context0->Exit();
   10485           6 : }
   10486             : 
   10487             : 
   10488       25880 : TEST(Regress470113) {
   10489           5 :   v8::Isolate* isolate = CcTest::isolate();
   10490           5 :   v8::HandleScope handle_scope(isolate);
   10491           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   10492           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   10493          10 :   LocalContext env;
   10494          30 :   CHECK(env->Global()
   10495             :             ->Set(env.local(), v8_str("prohibited"),
   10496             :                   obj_template->NewInstance(env.local()).ToLocalChecked())
   10497             :             .FromJust());
   10498             : 
   10499             :   {
   10500           5 :     v8::TryCatch try_catch(isolate);
   10501             :     CompileRun(
   10502             :         "'use strict';\n"
   10503             :         "class C extends Object {\n"
   10504             :         "   m() { super.powned = 'Powned!'; }\n"
   10505             :         "}\n"
   10506             :         "let c = new C();\n"
   10507             :         "c.m.call(prohibited)");
   10508             : 
   10509           5 :     CHECK(try_catch.HasCaught());
   10510           5 :   }
   10511           5 : }
   10512             : 
   10513             : 
   10514           6 : static void ConstTenGetter(Local<String> name,
   10515             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   10516           6 :   info.GetReturnValue().Set(v8_num(10));
   10517           6 : }
   10518             : 
   10519             : 
   10520       25881 : THREADED_TEST(CrossDomainAccessors) {
   10521           6 :   v8::Isolate* isolate = CcTest::isolate();
   10522           6 :   v8::HandleScope handle_scope(isolate);
   10523             : 
   10524             :   v8::Local<v8::FunctionTemplate> func_template =
   10525           6 :       v8::FunctionTemplate::New(isolate);
   10526             : 
   10527             :   v8::Local<v8::ObjectTemplate> global_template =
   10528           6 :       func_template->InstanceTemplate();
   10529             : 
   10530             :   v8::Local<v8::ObjectTemplate> proto_template =
   10531           6 :       func_template->PrototypeTemplate();
   10532             : 
   10533             :   // Add an accessor to proto that's accessible by cross-domain JS code.
   10534             :   proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, nullptr,
   10535          12 :                               v8::Local<Value>(), v8::ALL_CAN_READ);
   10536             : 
   10537             :   // Add an accessor that is not accessible by cross-domain JS code.
   10538             :   global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter,
   10539          12 :                                nullptr, v8::Local<Value>(), v8::DEFAULT);
   10540             : 
   10541           6 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, global_template);
   10542           6 :   context0->Enter();
   10543             : 
   10544           6 :   Local<v8::Object> global = context0->Global();
   10545             :   // Add a normal property that shadows 'accessible'
   10546          18 :   CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
   10547             : 
   10548             :   // Enter a new context.
   10549          12 :   v8::HandleScope scope1(CcTest::isolate());
   10550           6 :   v8::Local<Context> context1 = Context::New(isolate);
   10551           6 :   context1->Enter();
   10552             : 
   10553           6 :   v8::Local<v8::Object> global1 = context1->Global();
   10554          18 :   CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
   10555             : 
   10556             :   // Should return 10, instead of 11
   10557             :   v8::Local<Value> value =
   10558           6 :       v8_compile("other.accessible")->Run(context1).ToLocalChecked();
   10559           6 :   CHECK(value->IsNumber());
   10560          12 :   CHECK_EQ(10, value->Int32Value(context1).FromJust());
   10561             : 
   10562             :   v8::MaybeLocal<v8::Value> maybe_value =
   10563           6 :       v8_compile("other.unreachable")->Run(context1);
   10564           6 :   CHECK(maybe_value.IsEmpty());
   10565             : 
   10566           6 :   context1->Exit();
   10567          12 :   context0->Exit();
   10568           6 : }
   10569             : 
   10570             : 
   10571             : static int access_count = 0;
   10572             : 
   10573         820 : static bool AccessCounter(Local<v8::Context> accessing_context,
   10574             :                           Local<v8::Object> accessed_object,
   10575             :                           Local<v8::Value> data) {
   10576         820 :   access_count++;
   10577         820 :   return true;
   10578             : }
   10579             : 
   10580             : 
   10581             : // This one is too easily disturbed by other tests.
   10582       25880 : TEST(AccessControlIC) {
   10583           5 :   access_count = 0;
   10584             : 
   10585           5 :   v8::Isolate* isolate = CcTest::isolate();
   10586           5 :   v8::HandleScope handle_scope(isolate);
   10587             : 
   10588             :   // Create an environment.
   10589           5 :   v8::Local<Context> context0 = Context::New(isolate);
   10590           5 :   context0->Enter();
   10591             : 
   10592             :   // Create an object that requires access-check functions to be
   10593             :   // called for cross-domain access.
   10594             :   v8::Local<v8::ObjectTemplate> object_template =
   10595           5 :       v8::ObjectTemplate::New(isolate);
   10596           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   10597             :   Local<v8::Object> object =
   10598           5 :       object_template->NewInstance(context0).ToLocalChecked();
   10599             : 
   10600          10 :   v8::HandleScope scope1(isolate);
   10601             : 
   10602             :   // Create another environment.
   10603           5 :   v8::Local<Context> context1 = Context::New(isolate);
   10604           5 :   context1->Enter();
   10605             : 
   10606             :   // Make easy access to the object from the other environment.
   10607           5 :   v8::Local<v8::Object> global1 = context1->Global();
   10608          15 :   CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
   10609             : 
   10610             :   v8::Local<Value> value;
   10611             : 
   10612             :   // Check that the named access-control function is called every time.
   10613             :   CompileRun("function testProp(obj) {"
   10614             :              "  for (var i = 0; i < 10; i++) obj.prop = 1;"
   10615             :              "  for (var j = 0; j < 10; j++) obj.prop;"
   10616             :              "  return obj.prop"
   10617             :              "}");
   10618             :   value = CompileRun("testProp(obj)");
   10619           5 :   CHECK(value->IsNumber());
   10620          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10621           5 :   CHECK_EQ(21, access_count);
   10622             : 
   10623             :   // Check that the named access-control function is called every time.
   10624             :   CompileRun("var p = 'prop';"
   10625             :              "function testKeyed(obj) {"
   10626             :              "  for (var i = 0; i < 10; i++) obj[p] = 1;"
   10627             :              "  for (var j = 0; j < 10; j++) obj[p];"
   10628             :              "  return obj[p];"
   10629             :              "}");
   10630             :   // Use obj which requires access checks.  No inline caching is used
   10631             :   // in that case.
   10632             :   value = CompileRun("testKeyed(obj)");
   10633           5 :   CHECK(value->IsNumber());
   10634          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10635           5 :   CHECK_EQ(42, access_count);
   10636             :   // Force the inline caches into generic state and try again.
   10637             :   CompileRun("testKeyed({ a: 0 })");
   10638             :   CompileRun("testKeyed({ b: 0 })");
   10639             :   value = CompileRun("testKeyed(obj)");
   10640           5 :   CHECK(value->IsNumber());
   10641          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10642           5 :   CHECK_EQ(63, access_count);
   10643             : 
   10644             :   // Check that the indexed access-control function is called every time.
   10645           5 :   access_count = 0;
   10646             : 
   10647             :   CompileRun("function testIndexed(obj) {"
   10648             :              "  for (var i = 0; i < 10; i++) obj[0] = 1;"
   10649             :              "  for (var j = 0; j < 10; j++) obj[0];"
   10650             :              "  return obj[0]"
   10651             :              "}");
   10652             :   value = CompileRun("testIndexed(obj)");
   10653           5 :   CHECK(value->IsNumber());
   10654          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10655           5 :   CHECK_EQ(21, access_count);
   10656             :   // Force the inline caches into generic state.
   10657             :   CompileRun("testIndexed(new Array(1))");
   10658             :   // Test that the indexed access check is called.
   10659             :   value = CompileRun("testIndexed(obj)");
   10660           5 :   CHECK(value->IsNumber());
   10661          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10662           5 :   CHECK_EQ(42, access_count);
   10663             : 
   10664           5 :   access_count = 0;
   10665             :   // Check that the named access check is called when invoking
   10666             :   // functions on an object that requires access checks.
   10667             :   CompileRun("obj.f = function() {}");
   10668             :   CompileRun("function testCallNormal(obj) {"
   10669             :              "  for (var i = 0; i < 10; i++) obj.f();"
   10670             :              "}");
   10671             :   CompileRun("testCallNormal(obj)");
   10672           5 :   printf("%i\n", access_count);
   10673           5 :   CHECK_EQ(11, access_count);
   10674             : 
   10675             :   // Force obj into slow case.
   10676             :   value = CompileRun("delete obj.prop");
   10677           5 :   CHECK(value->BooleanValue(isolate));
   10678             :   // Force inline caches into dictionary probing mode.
   10679             :   CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
   10680             :   // Test that the named access check is called.
   10681             :   value = CompileRun("testProp(obj);");
   10682           5 :   CHECK(value->IsNumber());
   10683          10 :   CHECK_EQ(1, value->Int32Value(context1).FromJust());
   10684           5 :   CHECK_EQ(33, access_count);
   10685             : 
   10686             :   // Force the call inline cache into dictionary probing mode.
   10687             :   CompileRun("o.f = function() {}; testCallNormal(o)");
   10688             :   // Test that the named access check is still called for each
   10689             :   // invocation of the function.
   10690             :   value = CompileRun("testCallNormal(obj)");
   10691           5 :   CHECK_EQ(43, access_count);
   10692             : 
   10693           5 :   context1->Exit();
   10694          10 :   context0->Exit();
   10695           5 : }
   10696             : 
   10697             : 
   10698       25881 : THREADED_TEST(Version) { v8::V8::GetVersion(); }
   10699             : 
   10700             : 
   10701          18 : static void InstanceFunctionCallback(
   10702          18 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10703          18 :   ApiTestFuzzer::Fuzz();
   10704          18 :   args.GetReturnValue().Set(v8_num(12));
   10705          18 : }
   10706             : 
   10707             : 
   10708       25881 : THREADED_TEST(InstanceProperties) {
   10709           6 :   LocalContext context;
   10710           6 :   v8::Isolate* isolate = context->GetIsolate();
   10711          12 :   v8::HandleScope handle_scope(isolate);
   10712             : 
   10713           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10714           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10715             : 
   10716          18 :   instance->Set(v8_str("x"), v8_num(42));
   10717             :   instance->Set(v8_str("f"),
   10718          18 :                 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
   10719             : 
   10720           6 :   Local<Value> o = t->GetFunction(context.local())
   10721           6 :                        .ToLocalChecked()
   10722           6 :                        ->NewInstance(context.local())
   10723             :                        .ToLocalChecked();
   10724             : 
   10725          30 :   CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
   10726             :   Local<Value> value = CompileRun("i.x");
   10727          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   10728             : 
   10729             :   value = CompileRun("i.f()");
   10730          18 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10731           6 : }
   10732             : 
   10733             : 
   10734         696 : static void GlobalObjectInstancePropertiesGet(
   10735             :     Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
   10736         696 :   ApiTestFuzzer::Fuzz();
   10737         696 : }
   10738             : 
   10739             : 
   10740       25881 : THREADED_TEST(GlobalObjectInstanceProperties) {
   10741           6 :   v8::Isolate* isolate = CcTest::isolate();
   10742           6 :   v8::HandleScope handle_scope(isolate);
   10743             : 
   10744             :   Local<Value> global_object;
   10745             : 
   10746           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10747             :   t->InstanceTemplate()->SetHandler(
   10748          12 :       v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
   10749           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10750          18 :   instance_template->Set(v8_str("x"), v8_num(42));
   10751             :   instance_template->Set(v8_str("f"),
   10752             :                          v8::FunctionTemplate::New(isolate,
   10753          18 :                                                    InstanceFunctionCallback));
   10754             : 
   10755             :   // The script to check how TurboFan compiles missing global function
   10756             :   // invocations.  function g is not defined and should throw on call.
   10757             :   const char* script =
   10758             :       "function wrapper(call) {"
   10759             :       "  var x = 0, y = 1;"
   10760             :       "  for (var i = 0; i < 1000; i++) {"
   10761             :       "    x += i * 100;"
   10762             :       "    y += i * 100;"
   10763             :       "  }"
   10764             :       "  if (call) g();"
   10765             :       "}"
   10766             :       "for (var i = 0; i < 17; i++) wrapper(false);"
   10767             :       "var thrown = 0;"
   10768             :       "try { wrapper(true); } catch (e) { thrown = 1; };"
   10769             :       "thrown";
   10770             : 
   10771             :   {
   10772           6 :     LocalContext env(nullptr, instance_template);
   10773             :     // Hold on to the global object so it can be used again in another
   10774             :     // environment initialization.
   10775           6 :     global_object = env->Global();
   10776             : 
   10777             :     Local<Value> value = CompileRun("x");
   10778          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10779             :     value = CompileRun("f()");
   10780          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10781             :     value = CompileRun(script);
   10782          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10783             :   }
   10784             : 
   10785             :   {
   10786             :     // Create new environment reusing the global object.
   10787           6 :     LocalContext env(nullptr, instance_template, global_object);
   10788             :     Local<Value> value = CompileRun("x");
   10789          12 :     CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
   10790             :     value = CompileRun("f()");
   10791          12 :     CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
   10792             :     value = CompileRun(script);
   10793          12 :     CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
   10794           6 :   }
   10795           6 : }
   10796             : 
   10797       25881 : THREADED_TEST(ObjectGetOwnPropertyNames) {
   10798           6 :   LocalContext context;
   10799           6 :   v8::Isolate* isolate = context->GetIsolate();
   10800          12 :   v8::HandleScope handle_scope(isolate);
   10801             : 
   10802             :   v8::Local<v8::Object> value = v8::Local<v8::Object>::Cast(
   10803           6 :       v8::StringObject::New(CcTest::isolate(), v8_str("test")));
   10804             :   v8::Local<v8::Array> properties;
   10805             : 
   10806          12 :   CHECK(value
   10807             :             ->GetOwnPropertyNames(context.local(),
   10808             :                                   static_cast<v8::PropertyFilter>(
   10809             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10810             :                                       v8::PropertyFilter::SKIP_SYMBOLS),
   10811             :                                   v8::KeyConversionMode::kKeepNumbers)
   10812             :             .ToLocal(&properties));
   10813           6 :   CHECK_EQ(5u, properties->Length());
   10814             :   v8::Local<v8::Value> property;
   10815          18 :   CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
   10816             :         property->IsString());
   10817          18 :   CHECK(property.As<v8::String>()
   10818             :             ->Equals(context.local(), v8_str("length"))
   10819             :             .FromMaybe(false));
   10820          24 :   for (int i = 0; i < 4; ++i) {
   10821             :     v8::Local<v8::Value> property;
   10822          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
   10823             :           property->IsInt32());
   10824          24 :     CHECK_EQ(property.As<v8::Int32>()->Value(), i);
   10825             :   }
   10826             : 
   10827          12 :   CHECK(value
   10828             :             ->GetOwnPropertyNames(context.local(),
   10829             :                                   v8::PropertyFilter::ONLY_ENUMERABLE,
   10830             :                                   v8::KeyConversionMode::kKeepNumbers)
   10831             :             .ToLocal(&properties));
   10832             :   v8::Local<v8::Array> number_properties;
   10833          12 :   CHECK(value
   10834             :             ->GetOwnPropertyNames(context.local(),
   10835             :                                   v8::PropertyFilter::ONLY_ENUMERABLE,
   10836             :                                   v8::KeyConversionMode::kConvertToString)
   10837             :             .ToLocal(&number_properties));
   10838           6 :   CHECK_EQ(4u, properties->Length());
   10839          24 :   for (int i = 0; i < 4; ++i) {
   10840             :     v8::Local<v8::Value> property_index;
   10841             :     v8::Local<v8::Value> property_name;
   10842             : 
   10843          48 :     CHECK(number_properties->Get(context.local(), i).ToLocal(&property_name));
   10844          24 :     CHECK(property_name->IsString());
   10845             : 
   10846          48 :     CHECK(properties->Get(context.local(), i).ToLocal(&property_index));
   10847          24 :     CHECK(property_index->IsInt32());
   10848             : 
   10849          24 :     CHECK_EQ(property_index.As<v8::Int32>()->Value(), i);
   10850          48 :     CHECK_EQ(property_name->ToNumber(context.local())
   10851             :                  .ToLocalChecked()
   10852             :                  .As<v8::Int32>()
   10853             :                  ->Value(),
   10854             :              i);
   10855             :   }
   10856             : 
   10857           6 :   value = value->GetPrototype().As<v8::Object>();
   10858          12 :   CHECK(value
   10859             :             ->GetOwnPropertyNames(context.local(),
   10860             :                                   static_cast<v8::PropertyFilter>(
   10861             :                                       v8::PropertyFilter::ALL_PROPERTIES |
   10862             :                                       v8::PropertyFilter::SKIP_SYMBOLS))
   10863             :             .ToLocal(&properties));
   10864             :   bool concat_found = false;
   10865             :   bool starts_with_found = false;
   10866         288 :   for (uint32_t i = 0; i < properties->Length(); ++i) {
   10867             :     v8::Local<v8::Value> property;
   10868         576 :     CHECK(properties->Get(context.local(), i).ToLocal(&property));
   10869         288 :     if (!property->IsString()) continue;
   10870         288 :     if (!concat_found)
   10871             :       concat_found = property.As<v8::String>()
   10872         180 :                          ->Equals(context.local(), v8_str("concat"))
   10873         120 :                          .FromMaybe(false);
   10874         288 :     if (!starts_with_found)
   10875             :       starts_with_found = property.As<v8::String>()
   10876         648 :                               ->Equals(context.local(), v8_str("startsWith"))
   10877         432 :                               .FromMaybe(false);
   10878             :   }
   10879          12 :   CHECK(concat_found && starts_with_found);
   10880           6 : }
   10881             : 
   10882       25881 : THREADED_TEST(CallKnownGlobalReceiver) {
   10883           6 :   v8::Isolate* isolate = CcTest::isolate();
   10884           6 :   v8::HandleScope handle_scope(isolate);
   10885             : 
   10886             :   Local<Value> global_object;
   10887             : 
   10888           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10889           6 :   Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   10890             : 
   10891             :   // The script to check that we leave global object not
   10892             :   // global object proxy on stack when we deoptimize from inside
   10893             :   // arguments evaluation.
   10894             :   // To provoke error we need to both force deoptimization
   10895             :   // from arguments evaluation and to force CallIC to take
   10896             :   // CallIC_Miss code path that can't cope with global proxy.
   10897             :   const char* script =
   10898             :       "function bar(x, y) { try { } finally { } }"
   10899             :       "function baz(x) { try { } finally { } }"
   10900             :       "function bom(x) { try { } finally { } }"
   10901             :       "function foo(x) { bar([x], bom(2)); }"
   10902             :       "for (var i = 0; i < 10000; i++) foo(1);"
   10903             :       "foo";
   10904             : 
   10905             :   Local<Value> foo;
   10906             :   {
   10907           6 :     LocalContext env(nullptr, instance_template);
   10908             :     // Hold on to the global object so it can be used again in another
   10909             :     // environment initialization.
   10910           6 :     global_object = env->Global();
   10911           6 :     foo = CompileRun(script);
   10912             :   }
   10913             : 
   10914             :   {
   10915             :     // Create new environment reusing the global object.
   10916           6 :     LocalContext env(nullptr, instance_template, global_object);
   10917          30 :     CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
   10918           6 :     CompileRun("foo()");
   10919           6 :   }
   10920           6 : }
   10921             : 
   10922             : 
   10923           6 : static void ShadowFunctionCallback(
   10924           6 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   10925           6 :   ApiTestFuzzer::Fuzz();
   10926           6 :   args.GetReturnValue().Set(v8_num(42));
   10927           6 : }
   10928             : 
   10929             : 
   10930             : static int shadow_y;
   10931             : static int shadow_y_setter_call_count;
   10932             : static int shadow_y_getter_call_count;
   10933             : 
   10934             : 
   10935           6 : static void ShadowYSetter(Local<String>,
   10936             :                           Local<Value>,
   10937             :                           const v8::PropertyCallbackInfo<void>&) {
   10938           6 :   shadow_y_setter_call_count++;
   10939           6 :   shadow_y = 42;
   10940           6 : }
   10941             : 
   10942             : 
   10943           6 : static void ShadowYGetter(Local<String> name,
   10944             :                           const v8::PropertyCallbackInfo<v8::Value>& info) {
   10945           6 :   ApiTestFuzzer::Fuzz();
   10946           6 :   shadow_y_getter_call_count++;
   10947           6 :   info.GetReturnValue().Set(v8_num(shadow_y));
   10948           6 : }
   10949             : 
   10950             : 
   10951           0 : static void ShadowIndexedGet(uint32_t index,
   10952             :                              const v8::PropertyCallbackInfo<v8::Value>&) {
   10953           0 : }
   10954             : 
   10955             : 
   10956          42 : static void ShadowNamedGet(Local<Name> key,
   10957          42 :                            const v8::PropertyCallbackInfo<v8::Value>&) {}
   10958             : 
   10959       25881 : THREADED_TEST(ShadowObject) {
   10960           6 :   shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
   10961           6 :   v8::Isolate* isolate = CcTest::isolate();
   10962           6 :   v8::HandleScope handle_scope(isolate);
   10963             : 
   10964           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   10965          12 :   LocalContext context(nullptr, global_template);
   10966             : 
   10967           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   10968             :   t->InstanceTemplate()->SetHandler(
   10969          12 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   10970             :   t->InstanceTemplate()->SetHandler(
   10971          12 :       v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
   10972           6 :   Local<ObjectTemplate> proto = t->PrototypeTemplate();
   10973           6 :   Local<ObjectTemplate> instance = t->InstanceTemplate();
   10974             : 
   10975             :   proto->Set(v8_str("f"),
   10976             :              v8::FunctionTemplate::New(isolate,
   10977             :                                        ShadowFunctionCallback,
   10978          18 :                                        Local<Value>()));
   10979          18 :   proto->Set(v8_str("x"), v8_num(12));
   10980             : 
   10981          12 :   instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
   10982             : 
   10983           6 :   Local<Value> o = t->GetFunction(context.local())
   10984           6 :                        .ToLocalChecked()
   10985           6 :                        ->NewInstance(context.local())
   10986             :                        .ToLocalChecked();
   10987          30 :   CHECK(context->Global()
   10988             :             ->Set(context.local(), v8_str("__proto__"), o)
   10989             :             .FromJust());
   10990             : 
   10991             :   Local<Value> value =
   10992             :       CompileRun("this.propertyIsEnumerable(0)");
   10993           6 :   CHECK(value->IsBoolean());
   10994           6 :   CHECK(!value->BooleanValue(isolate));
   10995             : 
   10996             :   value = CompileRun("x");
   10997          12 :   CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
   10998             : 
   10999             :   value = CompileRun("f()");
   11000          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11001             : 
   11002             :   CompileRun("y = 43");
   11003           6 :   CHECK_EQ(1, shadow_y_setter_call_count);
   11004             :   value = CompileRun("y");
   11005           6 :   CHECK_EQ(1, shadow_y_getter_call_count);
   11006          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11007           6 : }
   11008             : 
   11009       25881 : THREADED_TEST(ShadowObjectAndDataProperty) {
   11010             :   // Lite mode doesn't make use of feedback vectors, which is what we
   11011             :   // want to ensure has the correct form.
   11012           6 :   if (i::FLAG_lite_mode) return;
   11013             :   // This test mimics the kind of shadow property the Chromium embedder
   11014             :   // uses for undeclared globals. The IC subsystem has special handling
   11015             :   // for this case, using a PREMONOMORPHIC state to delay entering
   11016             :   // MONOMORPHIC state until enough information is available to support
   11017             :   // efficient access and good feedback for optimization.
   11018           6 :   v8::Isolate* isolate = CcTest::isolate();
   11019           6 :   v8::HandleScope handle_scope(isolate);
   11020             : 
   11021           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   11022          12 :   LocalContext context(nullptr, global_template);
   11023             : 
   11024           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11025             :   t->InstanceTemplate()->SetHandler(
   11026          12 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   11027             : 
   11028           6 :   Local<Value> o = t->GetFunction(context.local())
   11029           6 :                        .ToLocalChecked()
   11030           6 :                        ->NewInstance(context.local())
   11031             :                        .ToLocalChecked();
   11032          30 :   CHECK(context->Global()
   11033             :             ->Set(context.local(), v8_str("__proto__"), o)
   11034             :             .FromJust());
   11035             : 
   11036             :   CompileRun(
   11037             :       "function foo(x) { i = x; }"
   11038             :       "foo(0)");
   11039             : 
   11040             :   i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   11041             :       v8::Utils::OpenHandle(*context->Global()
   11042          24 :                                  ->Get(context.local(), v8_str("foo"))
   11043          12 :                                  .ToLocalChecked())));
   11044           6 :   CHECK(foo->has_feedback_vector());
   11045             :   i::FeedbackSlot slot = i::FeedbackVector::ToSlot(0);
   11046          12 :   i::FeedbackNexus nexus(foo->feedback_vector(), slot);
   11047           6 :   CHECK_EQ(i::FeedbackSlotKind::kStoreGlobalSloppy, nexus.kind());
   11048           6 :   CHECK_EQ(i::PREMONOMORPHIC, nexus.ic_state());
   11049             :   CompileRun("foo(1)");
   11050           6 :   CHECK_EQ(i::MONOMORPHIC, nexus.ic_state());
   11051             :   // We go a bit further, checking that the form of monomorphism is
   11052             :   // a PropertyCell in the vector. This is because we want to make sure
   11053             :   // we didn't settle for a "poor man's monomorphism," such as a
   11054             :   // slow_stub bailout which would mean a trip to the runtime on all
   11055             :   // subsequent stores, and a lack of feedback for the optimizing
   11056             :   // compiler downstream.
   11057           6 :   i::HeapObject heap_object;
   11058           6 :   CHECK(nexus.GetFeedback().GetHeapObject(&heap_object));
   11059          12 :   CHECK(heap_object->IsPropertyCell());
   11060             : }
   11061             : 
   11062       25881 : THREADED_TEST(ShadowObjectAndDataPropertyTurbo) {
   11063             :   // This test is the same as the previous one except that it triggers
   11064             :   // optimization of {foo} after its first invocation.
   11065           6 :   i::FLAG_allow_natives_syntax = true;
   11066             : 
   11067           6 :   if (i::FLAG_lite_mode) return;
   11068           6 :   v8::Isolate* isolate = CcTest::isolate();
   11069           6 :   v8::HandleScope handle_scope(isolate);
   11070             : 
   11071           6 :   Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   11072          12 :   LocalContext context(nullptr, global_template);
   11073             : 
   11074           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11075             :   t->InstanceTemplate()->SetHandler(
   11076          12 :       v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
   11077             : 
   11078           6 :   Local<Value> o = t->GetFunction(context.local())
   11079           6 :                        .ToLocalChecked()
   11080           6 :                        ->NewInstance(context.local())
   11081             :                        .ToLocalChecked();
   11082          30 :   CHECK(context->Global()
   11083             :             ->Set(context.local(), v8_str("__proto__"), o)
   11084             :             .FromJust());
   11085             : 
   11086             :   CompileRun(
   11087             :       "function foo(x) { i = x; }"
   11088             :       "foo(0)");
   11089             : 
   11090             :   i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   11091             :       v8::Utils::OpenHandle(*context->Global()
   11092          24 :                                  ->Get(context.local(), v8_str("foo"))
   11093          12 :                                  .ToLocalChecked())));
   11094           6 :   CHECK(foo->has_feedback_vector());
   11095             :   i::FeedbackSlot slot = i::FeedbackVector::ToSlot(0);
   11096          12 :   i::FeedbackNexus nexus(foo->feedback_vector(), slot);
   11097           6 :   CHECK_EQ(i::FeedbackSlotKind::kStoreGlobalSloppy, nexus.kind());
   11098           6 :   CHECK_EQ(i::PREMONOMORPHIC, nexus.ic_state());
   11099             :   CompileRun("%OptimizeFunctionOnNextCall(foo); foo(1)");
   11100           6 :   CHECK_EQ(i::MONOMORPHIC, nexus.ic_state());
   11101           6 :   i::HeapObject heap_object;
   11102           6 :   CHECK(nexus.GetFeedback().GetHeapObject(&heap_object));
   11103          12 :   CHECK(heap_object->IsPropertyCell());
   11104             : }
   11105             : 
   11106       25881 : THREADED_TEST(SetPrototype) {
   11107           6 :   LocalContext context;
   11108           6 :   v8::Isolate* isolate = context->GetIsolate();
   11109          12 :   v8::HandleScope handle_scope(isolate);
   11110             : 
   11111           6 :   Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
   11112          24 :   t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
   11113           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11114          24 :   t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
   11115           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11116          24 :   t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
   11117           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11118          24 :   t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
   11119             : 
   11120           6 :   Local<v8::Object> o0 = t0->GetFunction(context.local())
   11121           6 :                              .ToLocalChecked()
   11122           6 :                              ->NewInstance(context.local())
   11123             :                              .ToLocalChecked();
   11124           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11125           6 :                              .ToLocalChecked()
   11126           6 :                              ->NewInstance(context.local())
   11127             :                              .ToLocalChecked();
   11128           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11129           6 :                              .ToLocalChecked()
   11130           6 :                              ->NewInstance(context.local())
   11131             :                              .ToLocalChecked();
   11132           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11133           6 :                              .ToLocalChecked()
   11134           6 :                              ->NewInstance(context.local())
   11135             :                              .ToLocalChecked();
   11136             : 
   11137          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11138             :                   .ToLocalChecked()
   11139             :                   ->Int32Value(context.local())
   11140             :                   .FromJust());
   11141          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11142          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11143             :                   .ToLocalChecked()
   11144             :                   ->Int32Value(context.local())
   11145             :                   .FromJust());
   11146          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11147             :                   .ToLocalChecked()
   11148             :                   ->Int32Value(context.local())
   11149             :                   .FromJust());
   11150          12 :   CHECK(o1->SetPrototype(context.local(), o2).FromJust());
   11151          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11152             :                   .ToLocalChecked()
   11153             :                   ->Int32Value(context.local())
   11154             :                   .FromJust());
   11155          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11156             :                   .ToLocalChecked()
   11157             :                   ->Int32Value(context.local())
   11158             :                   .FromJust());
   11159          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11160             :                   .ToLocalChecked()
   11161             :                   ->Int32Value(context.local())
   11162             :                   .FromJust());
   11163          12 :   CHECK(o2->SetPrototype(context.local(), o3).FromJust());
   11164          24 :   CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
   11165             :                   .ToLocalChecked()
   11166             :                   ->Int32Value(context.local())
   11167             :                   .FromJust());
   11168          24 :   CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
   11169             :                   .ToLocalChecked()
   11170             :                   ->Int32Value(context.local())
   11171             :                   .FromJust());
   11172          24 :   CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
   11173             :                   .ToLocalChecked()
   11174             :                   ->Int32Value(context.local())
   11175             :                   .FromJust());
   11176          24 :   CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
   11177             :                   .ToLocalChecked()
   11178             :                   ->Int32Value(context.local())
   11179             :                   .FromJust());
   11180             : 
   11181             :   Local<Value> proto =
   11182          18 :       o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   11183           6 :   CHECK(proto->IsObject());
   11184          12 :   CHECK(proto.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   11185             : 
   11186           6 :   Local<Value> proto0 = o0->GetPrototype();
   11187           6 :   CHECK(proto0->IsObject());
   11188          12 :   CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
   11189             : 
   11190           6 :   Local<Value> proto1 = o1->GetPrototype();
   11191           6 :   CHECK(proto1->IsObject());
   11192          12 :   CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
   11193             : 
   11194           6 :   Local<Value> proto2 = o2->GetPrototype();
   11195           6 :   CHECK(proto2->IsObject());
   11196          18 :   CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
   11197           6 : }
   11198             : 
   11199             : 
   11200             : // Getting property names of an object with a prototype chain that
   11201             : // triggers dictionary elements in GetOwnPropertyNames() shouldn't
   11202             : // crash the runtime.
   11203       25881 : THREADED_TEST(Regress91517) {
   11204           6 :   i::FLAG_allow_natives_syntax = true;
   11205           6 :   LocalContext context;
   11206           6 :   v8::Isolate* isolate = context->GetIsolate();
   11207          12 :   v8::HandleScope handle_scope(isolate);
   11208             : 
   11209           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11210          24 :   t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
   11211           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11212          24 :   t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
   11213          12 :   t2->InstanceTemplate()->Set(v8_str("objects"),
   11214          24 :                               v8::ObjectTemplate::New(isolate));
   11215          24 :   t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
   11216           6 :   Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
   11217          24 :   t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
   11218           6 :   Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
   11219          24 :   t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
   11220             : 
   11221             :   // Force dictionary-based properties.
   11222             :   i::ScopedVector<char> name_buf(1024);
   11223        6006 :   for (int i = 1; i <= 1000; i++) {
   11224        6000 :     i::SNPrintF(name_buf, "sdf%d", i);
   11225       24000 :     t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
   11226             :   }
   11227             : 
   11228           6 :   Local<v8::Object> o1 = t1->GetFunction(context.local())
   11229           6 :                              .ToLocalChecked()
   11230           6 :                              ->NewInstance(context.local())
   11231             :                              .ToLocalChecked();
   11232           6 :   Local<v8::Object> o2 = t2->GetFunction(context.local())
   11233           6 :                              .ToLocalChecked()
   11234           6 :                              ->NewInstance(context.local())
   11235             :                              .ToLocalChecked();
   11236           6 :   Local<v8::Object> o3 = t3->GetFunction(context.local())
   11237           6 :                              .ToLocalChecked()
   11238           6 :                              ->NewInstance(context.local())
   11239             :                              .ToLocalChecked();
   11240           6 :   Local<v8::Object> o4 = t4->GetFunction(context.local())
   11241           6 :                              .ToLocalChecked()
   11242           6 :                              ->NewInstance(context.local())
   11243             :                              .ToLocalChecked();
   11244             : 
   11245          12 :   CHECK(o4->SetPrototype(context.local(), o3).FromJust());
   11246          12 :   CHECK(o3->SetPrototype(context.local(), o2).FromJust());
   11247          12 :   CHECK(o2->SetPrototype(context.local(), o1).FromJust());
   11248             : 
   11249             :   // Call the runtime version of GetOwnPropertyNames() on the natively
   11250             :   // created object through JavaScript.
   11251          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
   11252             :   // PROPERTY_FILTER_NONE = 0
   11253             :   CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
   11254             : 
   11255           6 :   ExpectInt32("names.length", 1);
   11256             :   ExpectTrue("names.indexOf(\"baz\") >= 0");
   11257             :   ExpectFalse("names.indexOf(\"boo\") >= 0");
   11258             :   ExpectFalse("names.indexOf(\"foo\") >= 0");
   11259             :   ExpectFalse("names.indexOf(\"fuz1\") >= 0");
   11260             :   ExpectFalse("names.indexOf(\"objects\") >= 0");
   11261             :   ExpectFalse("names.indexOf(\"fuz2\") >= 0");
   11262           6 :   ExpectTrue("names[1005] == undefined");
   11263           6 : }
   11264             : 
   11265             : 
   11266       25881 : THREADED_TEST(FunctionReadOnlyPrototype) {
   11267           6 :   LocalContext context;
   11268           6 :   v8::Isolate* isolate = context->GetIsolate();
   11269          12 :   v8::HandleScope handle_scope(isolate);
   11270             : 
   11271           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11272          24 :   t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11273           6 :   t1->ReadOnlyPrototype();
   11274          36 :   CHECK(context->Global()
   11275             :             ->Set(context.local(), v8_str("func1"),
   11276             :                   t1->GetFunction(context.local()).ToLocalChecked())
   11277             :             .FromJust());
   11278             :   // Configured value of ReadOnly flag.
   11279           6 :   CHECK(
   11280             :       CompileRun(
   11281             :           "(function() {"
   11282             :           "  descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
   11283             :           "  return (descriptor['writable'] == false);"
   11284             :           "})()")
   11285             :           ->BooleanValue(isolate));
   11286          18 :   CHECK_EQ(
   11287             :       42,
   11288             :       CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
   11289          18 :   CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
   11290             :                    ->Int32Value(context.local())
   11291             :                    .FromJust());
   11292             : 
   11293           6 :   Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
   11294          24 :   t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
   11295          36 :   CHECK(context->Global()
   11296             :             ->Set(context.local(), v8_str("func2"),
   11297             :                   t2->GetFunction(context.local()).ToLocalChecked())
   11298             :             .FromJust());
   11299             :   // Default value of ReadOnly flag.
   11300           6 :   CHECK(
   11301             :       CompileRun(
   11302             :           "(function() {"
   11303             :           "  descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
   11304             :           "  return (descriptor['writable'] == true);"
   11305             :           "})()")
   11306             :           ->BooleanValue(isolate));
   11307          18 :   CHECK_EQ(
   11308             :       42,
   11309           6 :       CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
   11310           6 : }
   11311             : 
   11312             : 
   11313       25881 : THREADED_TEST(SetPrototypeThrows) {
   11314           6 :   LocalContext context;
   11315           6 :   v8::Isolate* isolate = context->GetIsolate();
   11316          12 :   v8::HandleScope handle_scope(isolate);
   11317             : 
   11318           6 :   Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11319             : 
   11320           6 :   Local<v8::Object> o0 = t->GetFunction(context.local())
   11321           6 :                              .ToLocalChecked()
   11322           6 :                              ->NewInstance(context.local())
   11323             :                              .ToLocalChecked();
   11324           6 :   Local<v8::Object> o1 = t->GetFunction(context.local())
   11325           6 :                              .ToLocalChecked()
   11326           6 :                              ->NewInstance(context.local())
   11327             :                              .ToLocalChecked();
   11328             : 
   11329          12 :   CHECK(o0->SetPrototype(context.local(), o1).FromJust());
   11330             :   // If setting the prototype leads to the cycle, SetPrototype should
   11331             :   // return false and keep VM in sane state.
   11332          12 :   v8::TryCatch try_catch(isolate);
   11333          12 :   CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
   11334           6 :   CHECK(!try_catch.HasCaught());
   11335           6 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   11336             : 
   11337          18 :   CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
   11338             :                    ->Int32Value(context.local())
   11339           6 :                    .FromJust());
   11340           6 : }
   11341             : 
   11342             : 
   11343       25881 : THREADED_TEST(FunctionRemovePrototype) {
   11344           6 :   LocalContext context;
   11345           6 :   v8::Isolate* isolate = context->GetIsolate();
   11346          12 :   v8::HandleScope handle_scope(isolate);
   11347             : 
   11348           6 :   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   11349           6 :   t1->RemovePrototype();
   11350           6 :   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
   11351           6 :   CHECK(!fun->IsConstructor());
   11352          30 :   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   11353           6 :   CHECK(!CompileRun("'prototype' in fun")->BooleanValue(isolate));
   11354             : 
   11355          12 :   v8::TryCatch try_catch(isolate);
   11356             :   CompileRun("new fun()");
   11357           6 :   CHECK(try_catch.HasCaught());
   11358             : 
   11359           6 :   try_catch.Reset();
   11360          12 :   CHECK(fun->NewInstance(context.local()).IsEmpty());
   11361          12 :   CHECK(try_catch.HasCaught());
   11362           6 : }
   11363             : 
   11364             : 
   11365       25881 : THREADED_TEST(GetterSetterExceptions) {
   11366           6 :   LocalContext context;
   11367           6 :   v8::Isolate* isolate = context->GetIsolate();
   11368          12 :   v8::HandleScope handle_scope(isolate);
   11369             :   CompileRun(
   11370             :       "function Foo() { };"
   11371             :       "function Throw() { throw 5; };"
   11372             :       "var x = { };"
   11373             :       "x.__defineSetter__('set', Throw);"
   11374             :       "x.__defineGetter__('get', Throw);");
   11375             :   Local<v8::Object> x = Local<v8::Object>::Cast(
   11376          30 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
   11377          12 :   v8::TryCatch try_catch(isolate);
   11378          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11379             :             .IsNothing());
   11380          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11381          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11382             :             .IsNothing());
   11383          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11384          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11385             :             .IsNothing());
   11386          18 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11387          24 :   CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
   11388             :             .IsNothing());
   11389          24 :   CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
   11390           6 : }
   11391             : 
   11392             : 
   11393       25881 : THREADED_TEST(Constructor) {
   11394           6 :   LocalContext context;
   11395           6 :   v8::Isolate* isolate = context->GetIsolate();
   11396          12 :   v8::HandleScope handle_scope(isolate);
   11397           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11398           6 :   templ->SetClassName(v8_str("Fun"));
   11399           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11400          30 :   CHECK(
   11401             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11402           6 :   Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
   11403             :   i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
   11404          12 :   CHECK(obj->IsJSObject());
   11405             :   Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
   11406          12 :   CHECK(value->BooleanValue(isolate));
   11407           6 : }
   11408             : 
   11409             : 
   11410       25881 : THREADED_TEST(FunctionDescriptorException) {
   11411           6 :   LocalContext context;
   11412           6 :   v8::Isolate* isolate = context->GetIsolate();
   11413          12 :   v8::HandleScope handle_scope(isolate);
   11414           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   11415           6 :   templ->SetClassName(v8_str("Fun"));
   11416           6 :   Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
   11417          30 :   CHECK(
   11418             :       context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
   11419             :   Local<Value> value = CompileRun(
   11420             :       "function test() {"
   11421             :       "  try {"
   11422             :       "    (new Fun()).blah()"
   11423             :       "  } catch (e) {"
   11424             :       "    var str = String(e);"
   11425             :       // "    if (str.indexOf('TypeError') == -1) return 1;"
   11426             :       // "    if (str.indexOf('[object Fun]') != -1) return 2;"
   11427             :       // "    if (str.indexOf('#<Fun>') == -1) return 3;"
   11428             :       "    return 0;"
   11429             :       "  }"
   11430             :       "  return 4;"
   11431             :       "}"
   11432             :       "test();");
   11433          18 :   CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
   11434           6 : }
   11435             : 
   11436             : 
   11437       25881 : THREADED_TEST(EvalAliasedDynamic) {
   11438           6 :   LocalContext current;
   11439          12 :   v8::HandleScope scope(current->GetIsolate());
   11440             : 
   11441             :   // Tests where aliased eval can only be resolved dynamically.
   11442             :   Local<Script> script = v8_compile(
   11443             :       "function f(x) { "
   11444             :       "  var foo = 2;"
   11445             :       "  with (x) { return eval('foo'); }"
   11446             :       "}"
   11447             :       "foo = 0;"
   11448             :       "result1 = f(new Object());"
   11449             :       "result2 = f(this);"
   11450             :       "var x = new Object();"
   11451             :       "x.eval = function(x) { return 1; };"
   11452             :       "result3 = f(x);");
   11453           6 :   script->Run(current.local()).ToLocalChecked();
   11454          36 :   CHECK_EQ(2, current->Global()
   11455             :                   ->Get(current.local(), v8_str("result1"))
   11456             :                   .ToLocalChecked()
   11457             :                   ->Int32Value(current.local())
   11458             :                   .FromJust());
   11459          36 :   CHECK_EQ(0, current->Global()
   11460             :                   ->Get(current.local(), v8_str("result2"))
   11461             :                   .ToLocalChecked()
   11462             :                   ->Int32Value(current.local())
   11463             :                   .FromJust());
   11464          36 :   CHECK_EQ(1, current->Global()
   11465             :                   ->Get(current.local(), v8_str("result3"))
   11466             :                   .ToLocalChecked()
   11467             :                   ->Int32Value(current.local())
   11468             :                   .FromJust());
   11469             : 
   11470          12 :   v8::TryCatch try_catch(current->GetIsolate());
   11471             :   script = v8_compile(
   11472             :       "function f(x) { "
   11473             :       "  var bar = 2;"
   11474             :       "  with (x) { return eval('bar'); }"
   11475             :       "}"
   11476             :       "result4 = f(this)");
   11477           6 :   script->Run(current.local()).ToLocalChecked();
   11478           6 :   CHECK(!try_catch.HasCaught());
   11479          36 :   CHECK_EQ(2, current->Global()
   11480             :                   ->Get(current.local(), v8_str("result4"))
   11481             :                   .ToLocalChecked()
   11482             :                   ->Int32Value(current.local())
   11483             :                   .FromJust());
   11484             : 
   11485          12 :   try_catch.Reset();
   11486           6 : }
   11487             : 
   11488             : 
   11489       25881 : THREADED_TEST(CrossEval) {
   11490           6 :   v8::HandleScope scope(CcTest::isolate());
   11491          12 :   LocalContext other;
   11492          12 :   LocalContext current;
   11493             : 
   11494           6 :   Local<String> token = v8_str("<security token>");
   11495           6 :   other->SetSecurityToken(token);
   11496           6 :   current->SetSecurityToken(token);
   11497             : 
   11498             :   // Set up reference from current to other.
   11499          36 :   CHECK(current->Global()
   11500             :             ->Set(current.local(), v8_str("other"), other->Global())
   11501             :             .FromJust());
   11502             : 
   11503             :   // Check that new variables are introduced in other context.
   11504             :   Local<Script> script = v8_compile("other.eval('var foo = 1234')");
   11505           6 :   script->Run(current.local()).ToLocalChecked();
   11506             :   Local<Value> foo =
   11507          30 :       other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
   11508          12 :   CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
   11509          30 :   CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
   11510             : 
   11511             :   // Check that writing to non-existing properties introduces them in
   11512             :   // the other context.
   11513             :   script = v8_compile("other.eval('na = 1234')");
   11514           6 :   script->Run(current.local()).ToLocalChecked();
   11515          36 :   CHECK_EQ(1234, other->Global()
   11516             :                      ->Get(current.local(), v8_str("na"))
   11517             :                      .ToLocalChecked()
   11518             :                      ->Int32Value(other.local())
   11519             :                      .FromJust());
   11520          30 :   CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
   11521             : 
   11522             :   // Check that global variables in current context are not visible in other
   11523             :   // context.
   11524          12 :   v8::TryCatch try_catch(CcTest::isolate());
   11525             :   script = v8_compile("var bar = 42; other.eval('bar');");
   11526          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11527           6 :   CHECK(try_catch.HasCaught());
   11528           6 :   try_catch.Reset();
   11529             : 
   11530             :   // Check that local variables in current context are not visible in other
   11531             :   // context.
   11532             :   script = v8_compile(
   11533             :       "(function() { "
   11534             :       "  var baz = 87;"
   11535             :       "  return other.eval('baz');"
   11536             :       "})();");
   11537          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11538           6 :   CHECK(try_catch.HasCaught());
   11539           6 :   try_catch.Reset();
   11540             : 
   11541             :   // Check that global variables in the other environment are visible
   11542             :   // when evaluting code.
   11543          30 :   CHECK(other->Global()
   11544             :             ->Set(other.local(), v8_str("bis"), v8_num(1234))
   11545             :             .FromJust());
   11546             :   script = v8_compile("other.eval('bis')");
   11547          18 :   CHECK_EQ(1234, script->Run(current.local())
   11548             :                      .ToLocalChecked()
   11549             :                      ->Int32Value(current.local())
   11550             :                      .FromJust());
   11551           6 :   CHECK(!try_catch.HasCaught());
   11552             : 
   11553             :   // Check that the 'this' pointer points to the global object evaluating
   11554             :   // code.
   11555          36 :   CHECK(other->Global()
   11556             :             ->Set(current.local(), v8_str("t"), other->Global())
   11557             :             .FromJust());
   11558             :   script = v8_compile("other.eval('this == t')");
   11559           6 :   Local<Value> result = script->Run(current.local()).ToLocalChecked();
   11560           6 :   CHECK(result->IsTrue());
   11561           6 :   CHECK(!try_catch.HasCaught());
   11562             : 
   11563             :   // Check that variables introduced in with-statement are not visible in
   11564             :   // other context.
   11565             :   script = v8_compile("with({x:2}){other.eval('x')}");
   11566          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11567           6 :   CHECK(try_catch.HasCaught());
   11568           6 :   try_catch.Reset();
   11569             : 
   11570             :   // Check that you cannot use 'eval.call' with another object than the
   11571             :   // current global object.
   11572             :   script = v8_compile("other.y = 1; eval.call(other, 'y')");
   11573          12 :   CHECK(script->Run(current.local()).IsEmpty());
   11574          12 :   CHECK(try_catch.HasCaught());
   11575           6 : }
   11576             : 
   11577             : 
   11578             : // Test that calling eval in a context which has been detached from
   11579             : // its global proxy works.
   11580       25881 : THREADED_TEST(EvalInDetachedGlobal) {
   11581           6 :   v8::Isolate* isolate = CcTest::isolate();
   11582           6 :   v8::HandleScope scope(isolate);
   11583             : 
   11584           6 :   v8::Local<Context> context0 = Context::New(isolate);
   11585           6 :   v8::Local<Context> context1 = Context::New(isolate);
   11586           6 :   Local<String> token = v8_str("<security token>");
   11587           6 :   context0->SetSecurityToken(token);
   11588           6 :   context1->SetSecurityToken(token);
   11589             : 
   11590             :   // Set up function in context0 that uses eval from context0.
   11591           6 :   context0->Enter();
   11592             :   v8::Local<v8::Value> fun = CompileRun(
   11593             :       "var x = 42;"
   11594             :       "(function() {"
   11595             :       "  var e = eval;"
   11596             :       "  return function(s) { return e(s); }"
   11597           6 :       "})()");
   11598           6 :   context0->Exit();
   11599             : 
   11600             :   // Put the function into context1 and call it before and after
   11601             :   // detaching the global.  Before detaching, the call succeeds and
   11602             :   // after detaching undefined is returned.
   11603           6 :   context1->Enter();
   11604          24 :   CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
   11605             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   11606          12 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   11607           6 :   context0->DetachGlobal();
   11608             :   x_value = CompileRun("fun('x')");
   11609           6 :   CHECK(x_value->IsUndefined());
   11610           6 :   context1->Exit();
   11611           6 : }
   11612             : 
   11613             : 
   11614       25881 : THREADED_TEST(CrossLazyLoad) {
   11615           6 :   v8::HandleScope scope(CcTest::isolate());
   11616          12 :   LocalContext other;
   11617          12 :   LocalContext current;
   11618             : 
   11619           6 :   Local<String> token = v8_str("<security token>");
   11620           6 :   other->SetSecurityToken(token);
   11621           6 :   current->SetSecurityToken(token);
   11622             : 
   11623             :   // Set up reference from current to other.
   11624          36 :   CHECK(current->Global()
   11625             :             ->Set(current.local(), v8_str("other"), other->Global())
   11626             :             .FromJust());
   11627             : 
   11628             :   // Trigger lazy loading in other context.
   11629             :   Local<Script> script = v8_compile("other.eval('new Date(42)')");
   11630           6 :   Local<Value> value = script->Run(current.local()).ToLocalChecked();
   11631          18 :   CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
   11632           6 : }
   11633             : 
   11634             : 
   11635         102 : static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
   11636          48 :   ApiTestFuzzer::Fuzz();
   11637          48 :   if (args.IsConstructCall()) {
   11638           6 :     if (args[0]->IsInt32()) {
   11639             :       args.GetReturnValue().Set(
   11640             :           v8_num(-args[0]
   11641           6 :                       ->Int32Value(args.GetIsolate()->GetCurrentContext())
   11642          18 :                       .FromJust()));
   11643          54 :       return;
   11644             :     }
   11645             :   }
   11646             : 
   11647             :   args.GetReturnValue().Set(args[0]);
   11648             : }
   11649             : 
   11650             : 
   11651             : // Test that a call handler can be set for objects which will allow
   11652             : // non-function objects created through the API to be called as
   11653             : // functions.
   11654       25881 : THREADED_TEST(CallAsFunction) {
   11655           6 :   LocalContext context;
   11656           6 :   v8::Isolate* isolate = context->GetIsolate();
   11657          12 :   v8::HandleScope scope(isolate);
   11658             : 
   11659             :   {
   11660           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11661           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11662           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   11663           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11664           6 :                                      .ToLocalChecked()
   11665           6 :                                      ->NewInstance(context.local())
   11666             :                                      .ToLocalChecked();
   11667          30 :     CHECK(context->Global()
   11668             :               ->Set(context.local(), v8_str("obj"), instance)
   11669             :               .FromJust());
   11670           6 :     v8::TryCatch try_catch(isolate);
   11671             :     Local<Value> value;
   11672           6 :     CHECK(!try_catch.HasCaught());
   11673             : 
   11674             :     value = CompileRun("obj(42)");
   11675           6 :     CHECK(!try_catch.HasCaught());
   11676          12 :     CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   11677             : 
   11678             :     value = CompileRun("(function(o){return o(49)})(obj)");
   11679           6 :     CHECK(!try_catch.HasCaught());
   11680          12 :     CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
   11681             : 
   11682             :     // test special case of call as function
   11683             :     value = CompileRun("[obj]['0'](45)");
   11684           6 :     CHECK(!try_catch.HasCaught());
   11685          12 :     CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
   11686             : 
   11687             :     value = CompileRun(
   11688             :         "obj.call = Function.prototype.call;"
   11689             :         "obj.call(null, 87)");
   11690           6 :     CHECK(!try_catch.HasCaught());
   11691          12 :     CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
   11692             : 
   11693             :     // Regression tests for bug #1116356: Calling call through call/apply
   11694             :     // must work for non-function receivers.
   11695             :     const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
   11696             :     value = CompileRun(apply_99);
   11697           6 :     CHECK(!try_catch.HasCaught());
   11698          12 :     CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
   11699             : 
   11700             :     const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
   11701             :     value = CompileRun(call_17);
   11702           6 :     CHECK(!try_catch.HasCaught());
   11703          12 :     CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
   11704             : 
   11705             :     // Check that the call-as-function handler can be called through new.
   11706             :     value = CompileRun("new obj(43)");
   11707           6 :     CHECK(!try_catch.HasCaught());
   11708          12 :     CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
   11709             : 
   11710             :     // Check that the call-as-function handler can be called through
   11711             :     // the API.
   11712           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11713          12 :     value = instance->CallAsFunction(context.local(), instance, 1, args)
   11714           6 :                 .ToLocalChecked();
   11715           6 :     CHECK(!try_catch.HasCaught());
   11716          12 :     CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
   11717             :   }
   11718             : 
   11719             :   {
   11720           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11721           6 :     Local<ObjectTemplate> instance_template(t->InstanceTemplate());
   11722             :     USE(instance_template);
   11723           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11724           6 :                                      .ToLocalChecked()
   11725           6 :                                      ->NewInstance(context.local())
   11726             :                                      .ToLocalChecked();
   11727          30 :     CHECK(context->Global()
   11728             :               ->Set(context.local(), v8_str("obj2"), instance)
   11729             :               .FromJust());
   11730           6 :     v8::TryCatch try_catch(isolate);
   11731             :     Local<Value> value;
   11732           6 :     CHECK(!try_catch.HasCaught());
   11733             : 
   11734             :     // Call an object without call-as-function handler through the JS
   11735             :     value = CompileRun("obj2(28)");
   11736           6 :     CHECK(value.IsEmpty());
   11737           6 :     CHECK(try_catch.HasCaught());
   11738          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11739             :     // TODO(verwaest): Better message
   11740           6 :     CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
   11741           6 :     try_catch.Reset();
   11742             : 
   11743             :     // Call an object without call-as-function handler through the API
   11744           6 :     v8::Local<Value> args[] = {v8_num(28)};
   11745          12 :     CHECK(
   11746             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11747           6 :     CHECK(try_catch.HasCaught());
   11748          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11749           6 :     CHECK_EQ(0,
   11750             :              strcmp("TypeError: object is not a function", *exception_value2));
   11751          12 :     try_catch.Reset();
   11752             :   }
   11753             : 
   11754             :   {
   11755           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11756           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11757           6 :     instance_template->SetCallAsFunctionHandler(ThrowValue);
   11758           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11759           6 :                                      .ToLocalChecked()
   11760           6 :                                      ->NewInstance(context.local())
   11761             :                                      .ToLocalChecked();
   11762          30 :     CHECK(context->Global()
   11763             :               ->Set(context.local(), v8_str("obj3"), instance)
   11764             :               .FromJust());
   11765           6 :     v8::TryCatch try_catch(isolate);
   11766             :     Local<Value> value;
   11767           6 :     CHECK(!try_catch.HasCaught());
   11768             : 
   11769             :     // Catch the exception which is thrown by call-as-function handler
   11770             :     value = CompileRun("obj3(22)");
   11771           6 :     CHECK(try_catch.HasCaught());
   11772          12 :     String::Utf8Value exception_value1(isolate, try_catch.Exception());
   11773           6 :     CHECK_EQ(0, strcmp("22", *exception_value1));
   11774           6 :     try_catch.Reset();
   11775             : 
   11776           6 :     v8::Local<Value> args[] = {v8_num(23)};
   11777          12 :     CHECK(
   11778             :         instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
   11779           6 :     CHECK(try_catch.HasCaught());
   11780          12 :     String::Utf8Value exception_value2(isolate, try_catch.Exception());
   11781           6 :     CHECK_EQ(0, strcmp("23", *exception_value2));
   11782          12 :     try_catch.Reset();
   11783             :   }
   11784             : 
   11785             :   {
   11786           6 :     Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
   11787           6 :     Local<ObjectTemplate> instance_template = t->InstanceTemplate();
   11788           6 :     instance_template->SetCallAsFunctionHandler(ReturnThis);
   11789           6 :     Local<v8::Object> instance = t->GetFunction(context.local())
   11790           6 :                                      .ToLocalChecked()
   11791           6 :                                      ->NewInstance(context.local())
   11792             :                                      .ToLocalChecked();
   11793             : 
   11794             :     Local<v8::Value> a1 =
   11795             :         instance
   11796             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11797          12 :                              nullptr)
   11798           6 :             .ToLocalChecked();
   11799           6 :     CHECK(a1->StrictEquals(instance));
   11800             :     Local<v8::Value> a2 =
   11801          12 :         instance->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11802           6 :             .ToLocalChecked();
   11803           6 :     CHECK(a2->StrictEquals(instance));
   11804             :     Local<v8::Value> a3 =
   11805           6 :         instance->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11806           6 :             .ToLocalChecked();
   11807           6 :     CHECK(a3->StrictEquals(instance));
   11808             :     Local<v8::Value> a4 =
   11809          18 :         instance->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11810           6 :             .ToLocalChecked();
   11811           6 :     CHECK(a4->StrictEquals(instance));
   11812             :     Local<v8::Value> a5 =
   11813          12 :         instance->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11814           6 :             .ToLocalChecked();
   11815           6 :     CHECK(a5->StrictEquals(instance));
   11816             :   }
   11817             : 
   11818             :   {
   11819             :     CompileRun(
   11820             :         "function ReturnThisSloppy() {"
   11821             :         "  return this;"
   11822             :         "}"
   11823             :         "function ReturnThisStrict() {"
   11824             :         "  'use strict';"
   11825             :         "  return this;"
   11826             :         "}");
   11827             :     Local<Function> ReturnThisSloppy = Local<Function>::Cast(
   11828             :         context->Global()
   11829          24 :             ->Get(context.local(), v8_str("ReturnThisSloppy"))
   11830           6 :             .ToLocalChecked());
   11831             :     Local<Function> ReturnThisStrict = Local<Function>::Cast(
   11832             :         context->Global()
   11833          24 :             ->Get(context.local(), v8_str("ReturnThisStrict"))
   11834           6 :             .ToLocalChecked());
   11835             : 
   11836             :     Local<v8::Value> a1 =
   11837             :         ReturnThisSloppy
   11838             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11839          12 :                              nullptr)
   11840           6 :             .ToLocalChecked();
   11841          12 :     CHECK(a1->StrictEquals(context->Global()));
   11842             :     Local<v8::Value> a2 =
   11843             :         ReturnThisSloppy
   11844          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11845           6 :             .ToLocalChecked();
   11846          12 :     CHECK(a2->StrictEquals(context->Global()));
   11847             :     Local<v8::Value> a3 =
   11848             :         ReturnThisSloppy
   11849           6 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11850           6 :             .ToLocalChecked();
   11851           6 :     CHECK(a3->IsNumberObject());
   11852           6 :     CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
   11853             :     Local<v8::Value> a4 =
   11854             :         ReturnThisSloppy
   11855          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11856           6 :             .ToLocalChecked();
   11857           6 :     CHECK(a4->IsStringObject());
   11858          18 :     CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
   11859             :     Local<v8::Value> a5 =
   11860             :         ReturnThisSloppy
   11861          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11862           6 :             .ToLocalChecked();
   11863           6 :     CHECK(a5->IsBooleanObject());
   11864           6 :     CHECK(a5.As<v8::BooleanObject>()->ValueOf());
   11865             : 
   11866             :     Local<v8::Value> a6 =
   11867             :         ReturnThisStrict
   11868             :             ->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
   11869          12 :                              nullptr)
   11870           6 :             .ToLocalChecked();
   11871           6 :     CHECK(a6->IsUndefined());
   11872             :     Local<v8::Value> a7 =
   11873             :         ReturnThisStrict
   11874          12 :             ->CallAsFunction(context.local(), v8::Null(isolate), 0, nullptr)
   11875           6 :             .ToLocalChecked();
   11876           6 :     CHECK(a7->IsNull());
   11877             :     Local<v8::Value> a8 =
   11878             :         ReturnThisStrict
   11879           6 :             ->CallAsFunction(context.local(), v8_num(42), 0, nullptr)
   11880           6 :             .ToLocalChecked();
   11881           6 :     CHECK(a8->StrictEquals(v8_num(42)));
   11882             :     Local<v8::Value> a9 =
   11883             :         ReturnThisStrict
   11884          18 :             ->CallAsFunction(context.local(), v8_str("hello"), 0, nullptr)
   11885           6 :             .ToLocalChecked();
   11886          12 :     CHECK(a9->StrictEquals(v8_str("hello")));
   11887             :     Local<v8::Value> a10 =
   11888             :         ReturnThisStrict
   11889          12 :             ->CallAsFunction(context.local(), v8::True(isolate), 0, nullptr)
   11890           6 :             .ToLocalChecked();
   11891           6 :     CHECK(a10->StrictEquals(v8::True(isolate)));
   11892           6 :   }
   11893           6 : }
   11894             : 
   11895             : 
   11896             : // Check whether a non-function object is callable.
   11897       25881 : THREADED_TEST(CallableObject) {
   11898           6 :   LocalContext context;
   11899           6 :   v8::Isolate* isolate = context->GetIsolate();
   11900          12 :   v8::HandleScope scope(isolate);
   11901             : 
   11902             :   {
   11903           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11904           6 :     instance_template->SetCallAsFunctionHandler(call_as_function);
   11905             :     Local<Object> instance =
   11906           6 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11907           6 :     v8::TryCatch try_catch(isolate);
   11908             : 
   11909           6 :     CHECK(instance->IsCallable());
   11910           6 :     CHECK(!try_catch.HasCaught());
   11911             :   }
   11912             : 
   11913             :   {
   11914           6 :     Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
   11915             :     Local<Object> instance =
   11916          12 :         instance_template->NewInstance(context.local()).ToLocalChecked();
   11917           6 :     v8::TryCatch try_catch(isolate);
   11918             : 
   11919           6 :     CHECK(!instance->IsCallable());
   11920           6 :     CHECK(!try_catch.HasCaught());
   11921             :   }
   11922             : 
   11923             :   {
   11924             :     Local<FunctionTemplate> function_template =
   11925           6 :         FunctionTemplate::New(isolate, call_as_function);
   11926             :     Local<Function> function =
   11927          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   11928             :     Local<Object> instance = function;
   11929           6 :     v8::TryCatch try_catch(isolate);
   11930             : 
   11931           6 :     CHECK(instance->IsCallable());
   11932           6 :     CHECK(!try_catch.HasCaught());
   11933             :   }
   11934             : 
   11935             :   {
   11936           6 :     Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
   11937             :     Local<Function> function =
   11938          12 :         function_template->GetFunction(context.local()).ToLocalChecked();
   11939             :     Local<Object> instance = function;
   11940           6 :     v8::TryCatch try_catch(isolate);
   11941             : 
   11942           6 :     CHECK(instance->IsCallable());
   11943           6 :     CHECK(!try_catch.HasCaught());
   11944           6 :   }
   11945           6 : }
   11946             : 
   11947             : 
   11948       25881 : THREADED_TEST(Regress567998) {
   11949           6 :   LocalContext env;
   11950          12 :   v8::HandleScope scope(env->GetIsolate());
   11951             : 
   11952             :   Local<v8::FunctionTemplate> desc =
   11953           6 :       v8::FunctionTemplate::New(env->GetIsolate());
   11954          12 :   desc->InstanceTemplate()->MarkAsUndetectable();  // undetectable
   11955          12 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis);  // callable
   11956             : 
   11957           6 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   11958           6 :                               .ToLocalChecked()
   11959           6 :                               ->NewInstance(env.local())
   11960             :                               .ToLocalChecked();
   11961          30 :   CHECK(
   11962             :       env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
   11963             : 
   11964           6 :   ExpectString("undetectable.toString()", "[object Object]");
   11965           6 :   ExpectString("typeof undetectable", "undefined");
   11966           6 :   ExpectString("typeof(undetectable)", "undefined");
   11967           6 :   ExpectBoolean("typeof undetectable == 'undefined'", true);
   11968           6 :   ExpectBoolean("typeof undetectable == 'object'", false);
   11969           6 :   ExpectBoolean("if (undetectable) { true; } else { false; }", false);
   11970           6 :   ExpectBoolean("!undetectable", true);
   11971             : 
   11972           6 :   ExpectObject("true&&undetectable", obj);
   11973           6 :   ExpectBoolean("false&&undetectable", false);
   11974           6 :   ExpectBoolean("true||undetectable", true);
   11975           6 :   ExpectObject("false||undetectable", obj);
   11976             : 
   11977           6 :   ExpectObject("undetectable&&true", obj);
   11978           6 :   ExpectObject("undetectable&&false", obj);
   11979           6 :   ExpectBoolean("undetectable||true", true);
   11980           6 :   ExpectBoolean("undetectable||false", false);
   11981             : 
   11982           6 :   ExpectBoolean("undetectable==null", true);
   11983           6 :   ExpectBoolean("null==undetectable", true);
   11984           6 :   ExpectBoolean("undetectable==undefined", true);
   11985           6 :   ExpectBoolean("undefined==undetectable", true);
   11986           6 :   ExpectBoolean("undetectable==undetectable", true);
   11987             : 
   11988           6 :   ExpectBoolean("undetectable===null", false);
   11989           6 :   ExpectBoolean("null===undetectable", false);
   11990           6 :   ExpectBoolean("undetectable===undefined", false);
   11991           6 :   ExpectBoolean("undefined===undetectable", false);
   11992          12 :   ExpectBoolean("undetectable===undetectable", true);
   11993           6 : }
   11994             : 
   11995             : 
   11996        1206 : static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
   11997        1206 :   v8::HandleScope scope(isolate);
   11998        1206 :   if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
   11999      600000 :   for (int i = 0; i < iterations; i++) {
   12000      600000 :     Local<v8::Number> n(v8::Integer::New(isolate, 42));
   12001             :   }
   12002        1200 :   return Recurse(isolate, depth - 1, iterations);
   12003             : }
   12004             : 
   12005             : 
   12006       25881 : THREADED_TEST(HandleIteration) {
   12007             :   static const int kIterations = 500;
   12008             :   static const int kNesting = 200;
   12009           6 :   LocalContext context;
   12010           6 :   v8::Isolate* isolate = context->GetIsolate();
   12011          12 :   v8::HandleScope scope0(isolate);
   12012           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12013             :   {
   12014           6 :     v8::HandleScope scope1(isolate);
   12015           6 :     CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12016        3006 :     for (int i = 0; i < kIterations; i++) {
   12017        3000 :       Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12018        3000 :       CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
   12019             :     }
   12020             : 
   12021           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12022             :     {
   12023           6 :       v8::HandleScope scope2(CcTest::isolate());
   12024        3006 :       for (int j = 0; j < kIterations; j++) {
   12025        3000 :         Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
   12026        3000 :         CHECK_EQ(j + 1 + kIterations,
   12027             :                  v8::HandleScope::NumberOfHandles(isolate));
   12028           6 :       }
   12029             :     }
   12030           6 :     CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
   12031             :   }
   12032           6 :   CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
   12033          12 :   CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
   12034           6 : }
   12035             : 
   12036             : 
   12037        1100 : static void InterceptorCallICFastApi(
   12038             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12039        1100 :   ApiTestFuzzer::Fuzz();
   12040        1100 :   CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
   12041             :   int* call_count =
   12042        1100 :       reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
   12043        1100 :   ++(*call_count);
   12044        1100 :   if ((*call_count) % 20 == 0) {
   12045          55 :     CcTest::CollectAllGarbage();
   12046             :   }
   12047        1100 : }
   12048             : 
   12049        2200 : static void FastApiCallback_TrivialSignature(
   12050        8800 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12051        2200 :   ApiTestFuzzer::Fuzz();
   12052        2200 :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
   12053        2200 :   v8::Isolate* isolate = CcTest::isolate();
   12054        2200 :   CHECK_EQ(isolate, args.GetIsolate());
   12055        6600 :   CHECK(args.This()
   12056             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12057             :             .FromJust());
   12058        8800 :   CHECK(args.Data()
   12059             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12060             :             .FromJust());
   12061             :   args.GetReturnValue().Set(
   12062        8800 :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12063        2200 : }
   12064             : 
   12065             : static void FastApiCallback_SimpleSignature(
   12066             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12067             :   ApiTestFuzzer::Fuzz();
   12068             :   CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
   12069             :   v8::Isolate* isolate = CcTest::isolate();
   12070             :   CHECK_EQ(isolate, args.GetIsolate());
   12071             :   CHECK(args.This()
   12072             :             ->GetPrototype()
   12073             :             ->Equals(isolate->GetCurrentContext(), args.Holder())
   12074             :             .FromJust());
   12075             :   CHECK(args.Data()
   12076             :             ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
   12077             :             .FromJust());
   12078             :   // Note, we're using HasRealNamedProperty instead of Has to avoid
   12079             :   // invoking the interceptor again.
   12080             :   CHECK(args.Holder()
   12081             :             ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
   12082             :             .FromJust());
   12083             :   args.GetReturnValue().Set(
   12084             :       args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
   12085             : }
   12086             : 
   12087             : 
   12088             : // Helper to maximize the odds of object moving.
   12089         192 : static void GenerateSomeGarbage() {
   12090             :   CompileRun(
   12091             :       "var garbage;"
   12092             :       "for (var i = 0; i < 1000; i++) {"
   12093             :       "  garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
   12094             :       "}"
   12095             :       "garbage = undefined;");
   12096         192 : }
   12097             : 
   12098             : 
   12099         180 : void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12100             :   static int count = 0;
   12101         180 :   if (count++ % 3 == 0) {
   12102          60 :     CcTest::CollectAllGarbage();
   12103             :     // This should move the stub
   12104          60 :     GenerateSomeGarbage();  // This should ensure the old stub memory is flushed
   12105             :   }
   12106         180 : }
   12107             : 
   12108             : 
   12109       25881 : THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
   12110           6 :   LocalContext context;
   12111           6 :   v8::Isolate* isolate = context->GetIsolate();
   12112          12 :   v8::HandleScope scope(isolate);
   12113             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12114           6 :       v8::ObjectTemplate::New(isolate);
   12115             :   nativeobject_templ->Set(isolate, "callback",
   12116             :                           v8::FunctionTemplate::New(isolate,
   12117          12 :                                                     DirectApiCallback));
   12118             :   v8::Local<v8::Object> nativeobject_obj =
   12119           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12120          30 :   CHECK(context->Global()
   12121             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12122             :             .FromJust());
   12123             :   // call the api function multiple times to ensure direct call stub creation.
   12124             :   CompileRun(
   12125             :       "function f() {"
   12126             :       "  for (var i = 1; i <= 30; i++) {"
   12127             :       "    nativeobject.callback();"
   12128             :       "  }"
   12129             :       "}"
   12130           6 :       "f();");
   12131           6 : }
   12132             : 
   12133          30 : void ThrowingDirectApiCallback(
   12134          30 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12135          60 :   args.GetIsolate()->ThrowException(v8_str("g"));
   12136          30 : }
   12137             : 
   12138       25881 : THREADED_TEST(CallICFastApi_DirectCall_Throw) {
   12139           6 :   LocalContext context;
   12140           6 :   v8::Isolate* isolate = context->GetIsolate();
   12141          12 :   v8::HandleScope scope(isolate);
   12142             :   v8::Local<v8::ObjectTemplate> nativeobject_templ =
   12143           6 :       v8::ObjectTemplate::New(isolate);
   12144             :   nativeobject_templ->Set(
   12145             :       isolate, "callback",
   12146          12 :       v8::FunctionTemplate::New(isolate, ThrowingDirectApiCallback));
   12147             :   v8::Local<v8::Object> nativeobject_obj =
   12148           6 :       nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
   12149          30 :   CHECK(context->Global()
   12150             :             ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
   12151             :             .FromJust());
   12152             :   // call the api function multiple times to ensure direct call stub creation.
   12153             :   v8::Local<Value> result = CompileRun(
   12154             :       "var result = '';"
   12155             :       "function f() {"
   12156             :       "  for (var i = 1; i <= 5; i++) {"
   12157             :       "    try { nativeobject.callback(); } catch (e) { result += e; }"
   12158             :       "  }"
   12159             :       "}"
   12160           6 :       "f(); result;");
   12161          24 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12162           6 : }
   12163             : 
   12164             : static int p_getter_count_3;
   12165             : 
   12166         341 : static Local<Value> DoDirectGetter() {
   12167         341 :   if (++p_getter_count_3 % 3 == 0) {
   12168         110 :     CcTest::CollectAllGarbage();
   12169         110 :     GenerateSomeGarbage();
   12170             :   }
   12171         341 :   return v8_str("Direct Getter Result");
   12172             : }
   12173             : 
   12174         341 : static void DirectGetterCallback(
   12175             :     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12176         341 :   CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
   12177         341 :   info.GetReturnValue().Set(DoDirectGetter());
   12178         341 : }
   12179             : 
   12180             : template <typename Accessor>
   12181          11 : static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
   12182          11 :   LocalContext context;
   12183          11 :   v8::Isolate* isolate = context->GetIsolate();
   12184          22 :   v8::HandleScope scope(isolate);
   12185          11 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12186          11 :   obj->SetAccessor(v8_str("p1"), accessor);
   12187          66 :   CHECK(context->Global()
   12188             :             ->Set(context.local(), v8_str("o1"),
   12189             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12190             :             .FromJust());
   12191          11 :   p_getter_count_3 = 0;
   12192             :   v8::Local<v8::Value> result = CompileRun(
   12193             :       "function f() {"
   12194             :       "  for (var i = 0; i < 30; i++) o1.p1;"
   12195             :       "  return o1.p1"
   12196             :       "}"
   12197          11 :       "f();");
   12198          33 :   CHECK(v8_str("Direct Getter Result")
   12199             :             ->Equals(context.local(), result)
   12200             :             .FromJust());
   12201          22 :   CHECK_EQ(31, p_getter_count_3);
   12202          11 : }
   12203             : 
   12204       51766 : THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
   12205          11 :   LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
   12206          11 : }
   12207             : 
   12208          30 : void ThrowingDirectGetterCallback(
   12209             :     Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12210          60 :   info.GetIsolate()->ThrowException(v8_str("g"));
   12211          30 : }
   12212             : 
   12213       25881 : THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
   12214           6 :   LocalContext context;
   12215           6 :   v8::Isolate* isolate = context->GetIsolate();
   12216          12 :   v8::HandleScope scope(isolate);
   12217           6 :   v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
   12218           6 :   obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
   12219          36 :   CHECK(context->Global()
   12220             :             ->Set(context.local(), v8_str("o1"),
   12221             :                   obj->NewInstance(context.local()).ToLocalChecked())
   12222             :             .FromJust());
   12223             :   v8::Local<Value> result = CompileRun(
   12224             :       "var result = '';"
   12225             :       "for (var i = 0; i < 5; i++) {"
   12226             :       "    try { o1.p1; } catch (e) { result += e; }"
   12227             :       "}"
   12228           6 :       "result;");
   12229          24 :   CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
   12230           6 : }
   12231             : 
   12232       51766 : THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
   12233          11 :   int interceptor_call_count = 0;
   12234          11 :   v8::Isolate* isolate = CcTest::isolate();
   12235          11 :   v8::HandleScope scope(isolate);
   12236             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12237          11 :       v8::FunctionTemplate::New(isolate);
   12238             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12239             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12240          22 :       v8::Local<v8::Signature>());
   12241          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12242          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12243          11 :   v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
   12244             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   12245             :       InterceptorCallICFastApi, nullptr, nullptr, nullptr, nullptr,
   12246          22 :       v8::External::New(isolate, &interceptor_call_count)));
   12247          22 :   LocalContext context;
   12248             :   v8::Local<v8::Function> fun =
   12249          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12250          11 :   GenerateSomeGarbage();
   12251          66 :   CHECK(context->Global()
   12252             :             ->Set(context.local(), v8_str("o"),
   12253             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12254             :             .FromJust());
   12255             :   CompileRun(
   12256             :       "var result = 0;"
   12257             :       "for (var i = 0; i < 100; i++) {"
   12258             :       "  result = o.method(41);"
   12259             :       "}");
   12260          66 :   CHECK_EQ(42, context->Global()
   12261             :                    ->Get(context.local(), v8_str("result"))
   12262             :                    .ToLocalChecked()
   12263             :                    ->Int32Value(context.local())
   12264             :                    .FromJust());
   12265          22 :   CHECK_EQ(100, interceptor_call_count);
   12266          11 : }
   12267             : 
   12268       51766 : THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
   12269          11 :   v8::Isolate* isolate = CcTest::isolate();
   12270          11 :   v8::HandleScope scope(isolate);
   12271             :   v8::Local<v8::FunctionTemplate> fun_templ =
   12272          11 :       v8::FunctionTemplate::New(isolate);
   12273             :   v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
   12274             :       isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
   12275          22 :       v8::Local<v8::Signature>());
   12276          11 :   v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
   12277          22 :   proto_templ->Set(v8_str("method"), method_templ);
   12278          11 :   v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
   12279             :   USE(templ);
   12280          22 :   LocalContext context;
   12281             :   v8::Local<v8::Function> fun =
   12282          11 :       fun_templ->GetFunction(context.local()).ToLocalChecked();
   12283          11 :   GenerateSomeGarbage();
   12284          66 :   CHECK(context->Global()
   12285             :             ->Set(context.local(), v8_str("o"),
   12286             :                   fun->NewInstance(context.local()).ToLocalChecked())
   12287             :             .FromJust());
   12288             :   CompileRun(
   12289             :       "var result = 0;"
   12290             :       "for (var i = 0; i < 100; i++) {"
   12291             :       "  result = o.method(41);"
   12292             :       "}");
   12293             : 
   12294          66 :   CHECK_EQ(42, context->Global()
   12295             :                    ->Get(context.local(), v8_str("result"))
   12296             :                    .ToLocalChecked()
   12297             :                    ->Int32Value(context.local())
   12298          11 :                    .FromJust());
   12299          11 : }
   12300             : 
   12301          24 : static void ThrowingGetter(Local<String> name,
   12302             :                            const v8::PropertyCallbackInfo<v8::Value>& info) {
   12303          24 :   ApiTestFuzzer::Fuzz();
   12304          24 :   info.GetIsolate()->ThrowException(Local<Value>());
   12305             :   info.GetReturnValue().SetUndefined();
   12306          24 : }
   12307             : 
   12308             : 
   12309       25881 : THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
   12310           6 :   LocalContext context;
   12311          12 :   HandleScope scope(context->GetIsolate());
   12312             : 
   12313           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   12314           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12315          12 :   instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
   12316             : 
   12317           6 :   Local<Object> instance = templ->GetFunction(context.local())
   12318           6 :                                .ToLocalChecked()
   12319           6 :                                ->NewInstance(context.local())
   12320             :                                .ToLocalChecked();
   12321             : 
   12322           6 :   Local<Object> another = Object::New(context->GetIsolate());
   12323          12 :   CHECK(another->SetPrototype(context.local(), instance).FromJust());
   12324             : 
   12325             :   Local<Object> with_js_getter = CompileRun(
   12326             :       "o = {};\n"
   12327             :       "o.__defineGetter__('f', function() { throw undefined; });\n"
   12328             :       "o\n").As<Object>();
   12329           6 :   CHECK(!with_js_getter.IsEmpty());
   12330             : 
   12331          12 :   TryCatch try_catch(context->GetIsolate());
   12332             : 
   12333             :   v8::MaybeLocal<Value> result =
   12334          12 :       instance->GetRealNamedProperty(context.local(), v8_str("f"));
   12335           6 :   CHECK(try_catch.HasCaught());
   12336           6 :   try_catch.Reset();
   12337           6 :   CHECK(result.IsEmpty());
   12338             : 
   12339             :   Maybe<PropertyAttribute> attr =
   12340          12 :       instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12341           6 :   CHECK(!try_catch.HasCaught());
   12342           6 :   CHECK(Just(None) == attr);
   12343             : 
   12344          12 :   result = another->GetRealNamedProperty(context.local(), v8_str("f"));
   12345           6 :   CHECK(try_catch.HasCaught());
   12346           6 :   try_catch.Reset();
   12347           6 :   CHECK(result.IsEmpty());
   12348             : 
   12349          12 :   attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
   12350           6 :   CHECK(!try_catch.HasCaught());
   12351           6 :   CHECK(Just(None) == attr);
   12352             : 
   12353             :   result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
   12354          12 :                                                          v8_str("f"));
   12355           6 :   CHECK(try_catch.HasCaught());
   12356           6 :   try_catch.Reset();
   12357           6 :   CHECK(result.IsEmpty());
   12358             : 
   12359             :   attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
   12360          12 :       context.local(), v8_str("f"));
   12361           6 :   CHECK(!try_catch.HasCaught());
   12362           6 :   CHECK(Just(None) == attr);
   12363             : 
   12364          12 :   result = another->Get(context.local(), v8_str("f"));
   12365           6 :   CHECK(try_catch.HasCaught());
   12366           6 :   try_catch.Reset();
   12367           6 :   CHECK(result.IsEmpty());
   12368             : 
   12369          12 :   result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
   12370           6 :   CHECK(try_catch.HasCaught());
   12371           6 :   try_catch.Reset();
   12372           6 :   CHECK(result.IsEmpty());
   12373             : 
   12374             :   attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
   12375          12 :                                                         v8_str("f"));
   12376           6 :   CHECK(!try_catch.HasCaught());
   12377           6 :   CHECK(Just(None) == attr);
   12378             : 
   12379          12 :   result = with_js_getter->Get(context.local(), v8_str("f"));
   12380           6 :   CHECK(try_catch.HasCaught());
   12381           6 :   try_catch.Reset();
   12382           6 :   CHECK(result.IsEmpty());
   12383             : 
   12384             :   Local<Object> target = CompileRun("({})").As<Object>();
   12385           6 :   Local<Object> handler = CompileRun("({})").As<Object>();
   12386             :   Local<v8::Proxy> proxy =
   12387           6 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   12388             : 
   12389          12 :   result = target->GetRealNamedProperty(context.local(), v8_str("f"));
   12390           6 :   CHECK(!try_catch.HasCaught());
   12391           6 :   CHECK(result.IsEmpty());
   12392             : 
   12393          12 :   result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
   12394           6 :   CHECK(!try_catch.HasCaught());
   12395          12 :   CHECK(result.IsEmpty());
   12396           6 : }
   12397             : 
   12398             : 
   12399          30 : static void ThrowingCallbackWithTryCatch(
   12400          30 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12401          30 :   TryCatch try_catch(args.GetIsolate());
   12402             :   // Verboseness is important: it triggers message delivery which can call into
   12403             :   // external code.
   12404          30 :   try_catch.SetVerbose(true);
   12405             :   CompileRun("throw 'from JS';");
   12406          30 :   CHECK(try_catch.HasCaught());
   12407          30 :   CHECK(!CcTest::i_isolate()->has_pending_exception());
   12408          30 :   CHECK(!CcTest::i_isolate()->has_scheduled_exception());
   12409          30 : }
   12410             : 
   12411             : 
   12412             : static int call_depth;
   12413             : 
   12414             : 
   12415           6 : static void WithTryCatch(Local<Message> message, Local<Value> data) {
   12416           6 :   TryCatch try_catch(CcTest::isolate());
   12417           6 : }
   12418             : 
   12419             : 
   12420           6 : static void ThrowFromJS(Local<Message> message, Local<Value> data) {
   12421           6 :   if (--call_depth) CompileRun("throw 'ThrowInJS';");
   12422           6 : }
   12423             : 
   12424             : 
   12425           6 : static void ThrowViaApi(Local<Message> message, Local<Value> data) {
   12426          12 :   if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
   12427           6 : }
   12428             : 
   12429             : 
   12430           6 : static void WebKitLike(Local<Message> message, Local<Value> data) {
   12431           6 :   Local<String> errorMessageString = message->Get();
   12432           6 :   CHECK(!errorMessageString.IsEmpty());
   12433           6 :   message->GetStackTrace();
   12434           6 :   message->GetScriptOrigin().ResourceName();
   12435           6 : }
   12436             : 
   12437             : 
   12438       25881 : THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
   12439           6 :   LocalContext context;
   12440           6 :   v8::Isolate* isolate = context->GetIsolate();
   12441          12 :   HandleScope scope(isolate);
   12442             : 
   12443             :   Local<Function> func =
   12444           6 :       FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
   12445          18 :           ->GetFunction(context.local())
   12446           6 :           .ToLocalChecked();
   12447          30 :   CHECK(
   12448             :       context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
   12449             : 
   12450             :   MessageCallback callbacks[] = {nullptr, WebKitLike, ThrowViaApi, ThrowFromJS,
   12451           6 :                                  WithTryCatch};
   12452          36 :   for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
   12453          30 :     MessageCallback callback = callbacks[i];
   12454          30 :     if (callback != nullptr) {
   12455          24 :       isolate->AddMessageListener(callback);
   12456             :     }
   12457             :     // Some small number to control number of times message handler should
   12458             :     // throw an exception.
   12459          30 :     call_depth = 5;
   12460             :     ExpectFalse(
   12461             :         "var thrown = false;\n"
   12462             :         "try { func(); } catch(e) { thrown = true; }\n"
   12463             :         "thrown\n");
   12464          30 :     if (callback != nullptr) {
   12465          24 :       isolate->RemoveMessageListeners(callback);
   12466             :     }
   12467           6 :   }
   12468           6 : }
   12469             : 
   12470             : 
   12471           6 : static void ParentGetter(Local<String> name,
   12472             :                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   12473           6 :   ApiTestFuzzer::Fuzz();
   12474           6 :   info.GetReturnValue().Set(v8_num(1));
   12475           6 : }
   12476             : 
   12477             : 
   12478          18 : static void ChildGetter(Local<String> name,
   12479             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   12480          18 :   ApiTestFuzzer::Fuzz();
   12481          18 :   info.GetReturnValue().Set(v8_num(42));
   12482          18 : }
   12483             : 
   12484             : 
   12485       25881 : THREADED_TEST(Overriding) {
   12486           6 :   LocalContext context;
   12487           6 :   v8::Isolate* isolate = context->GetIsolate();
   12488          12 :   v8::HandleScope scope(isolate);
   12489             : 
   12490             :   // Parent template.
   12491           6 :   Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
   12492             :   Local<ObjectTemplate> parent_instance_templ =
   12493           6 :       parent_templ->InstanceTemplate();
   12494          12 :   parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
   12495             : 
   12496             :   // Template that inherits from the parent template.
   12497           6 :   Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
   12498             :   Local<ObjectTemplate> child_instance_templ =
   12499           6 :       child_templ->InstanceTemplate();
   12500           6 :   child_templ->Inherit(parent_templ);
   12501             :   // Override 'f'.  The child version of 'f' should get called for child
   12502             :   // instances.
   12503           6 :   child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
   12504             :   // Add 'g' twice.  The 'g' added last should get called for instances.
   12505           6 :   child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
   12506           6 :   child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
   12507             : 
   12508             :   // Add 'h' as an accessor to the proto template with ReadOnly attributes
   12509             :   // so 'h' can be shadowed on the instance object.
   12510           6 :   Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
   12511             :   child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, nullptr,
   12512          12 :                                  v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
   12513             : 
   12514             :   // Add 'i' as an accessor to the instance template with ReadOnly attributes
   12515             :   // but the attribute does not have effect because it is duplicated with
   12516             :   // nullptr setter.
   12517             :   child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, nullptr,
   12518             :                                     v8::Local<Value>(), v8::DEFAULT,
   12519           6 :                                     v8::ReadOnly);
   12520             : 
   12521             :   // Instantiate the child template.
   12522           6 :   Local<v8::Object> instance = child_templ->GetFunction(context.local())
   12523           6 :                                    .ToLocalChecked()
   12524           6 :                                    ->NewInstance(context.local())
   12525             :                                    .ToLocalChecked();
   12526             : 
   12527             :   // Check that the child function overrides the parent one.
   12528          30 :   CHECK(context->Global()
   12529             :             ->Set(context.local(), v8_str("o"), instance)
   12530             :             .FromJust());
   12531          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12532             :   // Check that the 'g' that was added last is hit.
   12533          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12534          12 :   value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
   12535          12 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12536             : 
   12537             :   // Check that 'h' cannot be shadowed.
   12538          12 :   value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
   12539          12 :   CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
   12540             : 
   12541             :   // Check that 'i' cannot be shadowed or changed.
   12542          12 :   value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
   12543          18 :   CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
   12544           6 : }
   12545             : 
   12546             : 
   12547          24 : static void ShouldThrowOnErrorGetter(
   12548             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
   12549          24 :   ApiTestFuzzer::Fuzz();
   12550             :   v8::Isolate* isolate = info.GetIsolate();
   12551             :   Local<Boolean> should_throw_on_error =
   12552             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12553             :   info.GetReturnValue().Set(should_throw_on_error);
   12554          24 : }
   12555             : 
   12556             : 
   12557             : template <typename T>
   12558          24 : static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
   12559             :                                      const v8::PropertyCallbackInfo<T>& info) {
   12560          24 :   ApiTestFuzzer::Fuzz();
   12561             :   v8::Isolate* isolate = info.GetIsolate();
   12562          24 :   auto context = isolate->GetCurrentContext();
   12563             :   Local<Boolean> should_throw_on_error_value =
   12564             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12565         120 :   CHECK(context->Global()
   12566             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
   12567             :                   should_throw_on_error_value)
   12568             :             .FromJust());
   12569          24 : }
   12570             : 
   12571             : 
   12572       25881 : THREADED_TEST(AccessorShouldThrowOnError) {
   12573           6 :   LocalContext context;
   12574           6 :   v8::Isolate* isolate = context->GetIsolate();
   12575          12 :   v8::HandleScope scope(isolate);
   12576           6 :   Local<Object> global = context->Global();
   12577             : 
   12578           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12579           6 :   Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
   12580             :   instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
   12581          12 :                               ShouldThrowOnErrorSetter<void>);
   12582             : 
   12583           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   12584           6 :                                    .ToLocalChecked()
   12585           6 :                                    ->NewInstance(context.local())
   12586             :                                    .ToLocalChecked();
   12587             : 
   12588          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   12589             : 
   12590             :   // SLOPPY mode
   12591          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12592           6 :   CHECK(value->IsFalse());
   12593          12 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   12594          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12595           6 :               .ToLocalChecked();
   12596           6 :   CHECK(value->IsFalse());
   12597             : 
   12598             :   // STRICT mode
   12599          12 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   12600           6 :   CHECK(value->IsFalse());
   12601          12 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   12602          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12603           6 :               .ToLocalChecked();
   12604          12 :   CHECK(value->IsTrue());
   12605           6 : }
   12606             : 
   12607             : 
   12608           0 : static void ShouldThrowOnErrorQuery(
   12609             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   12610           0 :   ApiTestFuzzer::Fuzz();
   12611             :   v8::Isolate* isolate = info.GetIsolate();
   12612             :   info.GetReturnValue().Set(v8::None);
   12613             : 
   12614           0 :   auto context = isolate->GetCurrentContext();
   12615             :   Local<Boolean> should_throw_on_error_value =
   12616             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12617           0 :   CHECK(context->Global()
   12618             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
   12619             :                   should_throw_on_error_value)
   12620             :             .FromJust());
   12621           0 : }
   12622             : 
   12623             : 
   12624          12 : static void ShouldThrowOnErrorDeleter(
   12625             :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
   12626          12 :   ApiTestFuzzer::Fuzz();
   12627             :   v8::Isolate* isolate = info.GetIsolate();
   12628             :   info.GetReturnValue().Set(v8::True(isolate));
   12629             : 
   12630          12 :   auto context = isolate->GetCurrentContext();
   12631             :   Local<Boolean> should_throw_on_error_value =
   12632             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12633          60 :   CHECK(context->Global()
   12634             :             ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
   12635             :                   should_throw_on_error_value)
   12636             :             .FromJust());
   12637          12 : }
   12638             : 
   12639             : 
   12640          12 : static void ShouldThrowOnErrorPropertyEnumerator(
   12641             :     const v8::PropertyCallbackInfo<v8::Array>& info) {
   12642          12 :   ApiTestFuzzer::Fuzz();
   12643             :   v8::Isolate* isolate = info.GetIsolate();
   12644          12 :   Local<v8::Array> names = v8::Array::New(isolate, 1);
   12645          36 :   CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
   12646             :   info.GetReturnValue().Set(names);
   12647             : 
   12648          12 :   auto context = isolate->GetCurrentContext();
   12649             :   Local<Boolean> should_throw_on_error_value =
   12650             :       Boolean::New(isolate, info.ShouldThrowOnError());
   12651          60 :   CHECK(context->Global()
   12652             :             ->Set(isolate->GetCurrentContext(),
   12653             :                   v8_str("should_throw_enumerator"),
   12654             :                   should_throw_on_error_value)
   12655             :             .FromJust());
   12656          12 : }
   12657             : 
   12658             : 
   12659       25881 : THREADED_TEST(InterceptorShouldThrowOnError) {
   12660           6 :   LocalContext context;
   12661           6 :   v8::Isolate* isolate = context->GetIsolate();
   12662          12 :   v8::HandleScope scope(isolate);
   12663           6 :   Local<Object> global = context->Global();
   12664             : 
   12665           6 :   auto interceptor_templ = v8::ObjectTemplate::New(isolate);
   12666             :   v8::NamedPropertyHandlerConfiguration handler(
   12667             :       ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
   12668             :       ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
   12669             :       ShouldThrowOnErrorPropertyEnumerator);
   12670           6 :   interceptor_templ->SetHandler(handler);
   12671             : 
   12672             :   Local<v8::Object> instance =
   12673           6 :       interceptor_templ->NewInstance(context.local()).ToLocalChecked();
   12674             : 
   12675          18 :   CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
   12676             : 
   12677             :   // SLOPPY mode
   12678          12 :   Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
   12679           6 :   CHECK(value->IsFalse());
   12680          12 :   v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
   12681          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12682           6 :               .ToLocalChecked();
   12683           6 :   CHECK(value->IsFalse());
   12684             : 
   12685          12 :   v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
   12686          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   12687           6 :               .ToLocalChecked();
   12688           6 :   CHECK(value->IsFalse());
   12689             : 
   12690             :   v8_compile("Object.getOwnPropertyNames(o)")
   12691           6 :       ->Run(context.local())
   12692           6 :       .ToLocalChecked();
   12693          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   12694           6 :               .ToLocalChecked();
   12695           6 :   CHECK(value->IsFalse());
   12696             : 
   12697             :   // STRICT mode
   12698          12 :   value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
   12699           6 :   CHECK(value->IsFalse());
   12700          12 :   v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
   12701          18 :   value = global->Get(context.local(), v8_str("should_throw_setter"))
   12702           6 :               .ToLocalChecked();
   12703           6 :   CHECK(value->IsTrue());
   12704             : 
   12705          12 :   v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
   12706          18 :   value = global->Get(context.local(), v8_str("should_throw_deleter"))
   12707           6 :               .ToLocalChecked();
   12708           6 :   CHECK(value->IsTrue());
   12709             : 
   12710             :   v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
   12711           6 :       ->Run(context.local())
   12712           6 :       .ToLocalChecked();
   12713          18 :   value = global->Get(context.local(), v8_str("should_throw_enumerator"))
   12714           6 :               .ToLocalChecked();
   12715          12 :   CHECK(value->IsFalse());
   12716           6 : }
   12717             : 
   12718          55 : static void EmptyHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {}
   12719             : 
   12720       25880 : TEST(CallHandlerHasNoSideEffect) {
   12721           5 :   v8::Isolate* isolate = CcTest::isolate();
   12722           5 :   v8::HandleScope scope(isolate);
   12723          10 :   LocalContext context;
   12724             : 
   12725             :   // Function template with call handler.
   12726           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12727           5 :   templ->SetCallHandler(EmptyHandler);
   12728          30 :   CHECK(context->Global()
   12729             :             ->Set(context.local(), v8_str("f"),
   12730             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12731             :             .FromJust());
   12732          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12733          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12734             : 
   12735             :   // Side-effect-free version.
   12736           5 :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
   12737             :   templ2->SetCallHandler(EmptyHandler, v8::Local<Value>(),
   12738           5 :                          v8::SideEffectType::kHasNoSideEffect);
   12739          30 :   CHECK(context->Global()
   12740             :             ->Set(context.local(), v8_str("f2"),
   12741             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   12742             :             .FromJust());
   12743           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12744          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12745           5 : }
   12746             : 
   12747       25880 : TEST(FunctionTemplateNewHasNoSideEffect) {
   12748           5 :   v8::Isolate* isolate = CcTest::isolate();
   12749           5 :   v8::HandleScope scope(isolate);
   12750          10 :   LocalContext context;
   12751             : 
   12752             :   // Function template with call handler.
   12753             :   Local<v8::FunctionTemplate> templ =
   12754           5 :       v8::FunctionTemplate::New(isolate, EmptyHandler);
   12755          35 :   CHECK(context->Global()
   12756             :             ->Set(context.local(), v8_str("f"),
   12757             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12758             :             .FromJust());
   12759          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12760          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12761             : 
   12762             :   // Side-effect-free version.
   12763             :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(
   12764             :       isolate, EmptyHandler, v8::Local<Value>(), v8::Local<v8::Signature>(), 0,
   12765           5 :       v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
   12766          35 :   CHECK(context->Global()
   12767             :             ->Set(context.local(), v8_str("f2"),
   12768             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   12769             :             .FromJust());
   12770           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12771          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12772           5 : }
   12773             : 
   12774       25880 : TEST(FunctionTemplateNewWithCacheHasNoSideEffect) {
   12775           5 :   v8::Isolate* isolate = CcTest::isolate();
   12776           5 :   v8::HandleScope scope(isolate);
   12777          10 :   LocalContext context;
   12778             :   v8::Local<v8::Private> priv =
   12779           5 :       v8::Private::ForApi(isolate, v8_str("Foo#draft"));
   12780             : 
   12781             :   // Function template with call handler.
   12782             :   Local<v8::FunctionTemplate> templ =
   12783           5 :       v8::FunctionTemplate::NewWithCache(isolate, EmptyHandler, priv);
   12784          35 :   CHECK(context->Global()
   12785             :             ->Set(context.local(), v8_str("f"),
   12786             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12787             :             .FromJust());
   12788          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12789          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12790             : 
   12791             :   // Side-effect-free version.
   12792             :   Local<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::NewWithCache(
   12793             :       isolate, EmptyHandler, priv, v8::Local<Value>(),
   12794           5 :       v8::Local<v8::Signature>(), 0, v8::SideEffectType::kHasNoSideEffect);
   12795          35 :   CHECK(context->Global()
   12796             :             ->Set(context.local(), v8_str("f2"),
   12797             :                   templ2->GetFunction(context.local()).ToLocalChecked())
   12798             :             .FromJust());
   12799           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12800          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12801           5 : }
   12802             : 
   12803       25880 : TEST(FunctionNewHasNoSideEffect) {
   12804           5 :   v8::Isolate* isolate = CcTest::isolate();
   12805           5 :   v8::HandleScope scope(isolate);
   12806          10 :   LocalContext context;
   12807             : 
   12808             :   // Function with side-effect.
   12809             :   Local<Function> func =
   12810          10 :       Function::New(context.local(), EmptyHandler).ToLocalChecked();
   12811          25 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func).FromJust());
   12812          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12813          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("new f()"), true).IsEmpty());
   12814             : 
   12815             :   // Side-effect-free version.
   12816             :   Local<Function> func2 =
   12817             :       Function::New(context.local(), EmptyHandler, Local<Value>(), 0,
   12818             :                     v8::ConstructorBehavior::kAllow,
   12819          10 :                     v8::SideEffectType::kHasNoSideEffect)
   12820           5 :           .ToLocalChecked();
   12821          25 :   CHECK(
   12822             :       context->Global()->Set(context.local(), v8_str("f2"), func2).FromJust());
   12823           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12824          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("new f2()"), true).ToLocalChecked();
   12825           5 : }
   12826             : 
   12827             : // These handlers instantiate a function the embedder considers safe in some
   12828             : // cases (e.g. "building object wrappers"), but those functions themselves were
   12829             : // not explicitly marked as side-effect-free.
   12830           5 : static void DefaultConstructHandler(
   12831           5 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   12832           5 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   12833             :   v8::Context::Scope context_scope(context);
   12834           5 :   v8::MaybeLocal<v8::Object> instance = Function::New(context, EmptyHandler)
   12835           5 :                                             .ToLocalChecked()
   12836           5 :                                             ->NewInstance(context, 0, nullptr);
   12837             :   USE(instance);
   12838           5 : }
   12839             : 
   12840          10 : static void NoSideEffectConstructHandler(
   12841          10 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   12842          10 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   12843             :   v8::Context::Scope context_scope(context);
   12844             :   v8::MaybeLocal<v8::Object> instance =
   12845          10 :       Function::New(context, EmptyHandler)
   12846          10 :           .ToLocalChecked()
   12847             :           ->NewInstanceWithSideEffectType(context, 0, nullptr,
   12848          10 :                                           v8::SideEffectType::kHasNoSideEffect);
   12849             :   USE(instance);
   12850          10 : }
   12851             : 
   12852           5 : static void NoSideEffectAndSideEffectConstructHandler(
   12853           5 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   12854           5 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
   12855             :   v8::Context::Scope context_scope(context);
   12856             :   // Constructs an instance in a side-effect-free way, followed by another with
   12857             :   // side effects.
   12858             :   v8::MaybeLocal<v8::Object> instance =
   12859           5 :       Function::New(context, EmptyHandler)
   12860           5 :           .ToLocalChecked()
   12861             :           ->NewInstanceWithSideEffectType(context, 0, nullptr,
   12862           5 :                                           v8::SideEffectType::kHasNoSideEffect);
   12863           5 :   v8::MaybeLocal<v8::Object> instance2 = Function::New(context, EmptyHandler)
   12864           5 :                                              .ToLocalChecked()
   12865           5 :                                              ->NewInstance(context, 0, nullptr);
   12866             :   USE(instance);
   12867             :   USE(instance2);
   12868           5 : }
   12869             : 
   12870       25880 : TEST(FunctionNewInstanceHasNoSideEffect) {
   12871           5 :   v8::Isolate* isolate = CcTest::isolate();
   12872           5 :   v8::HandleScope scope(isolate);
   12873          10 :   LocalContext context;
   12874             : 
   12875             :   // A whitelisted function that creates a new object with both side-effect
   12876             :   // free/full instantiations. Should throw.
   12877             :   Local<Function> func0 =
   12878             :       Function::New(context.local(), NoSideEffectAndSideEffectConstructHandler,
   12879             :                     Local<Value>(), 0, v8::ConstructorBehavior::kAllow,
   12880          10 :                     v8::SideEffectType::kHasNoSideEffect)
   12881           5 :           .ToLocalChecked();
   12882          25 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func0).FromJust());
   12883          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12884             : 
   12885             :   // A whitelisted function that creates a new object. Should throw.
   12886             :   Local<Function> func =
   12887             :       Function::New(context.local(), DefaultConstructHandler, Local<Value>(), 0,
   12888             :                     v8::ConstructorBehavior::kAllow,
   12889          10 :                     v8::SideEffectType::kHasNoSideEffect)
   12890           5 :           .ToLocalChecked();
   12891          25 :   CHECK(context->Global()->Set(context.local(), v8_str("f"), func).FromJust());
   12892          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f()"), true).IsEmpty());
   12893             : 
   12894             :   // A whitelisted function that creates a new object with explicit intent to
   12895             :   // have no side-effects (e.g. building an "object wrapper"). Should not throw.
   12896             :   Local<Function> func2 =
   12897             :       Function::New(context.local(), NoSideEffectConstructHandler,
   12898             :                     Local<Value>(), 0, v8::ConstructorBehavior::kAllow,
   12899          10 :                     v8::SideEffectType::kHasNoSideEffect)
   12900           5 :           .ToLocalChecked();
   12901          25 :   CHECK(
   12902             :       context->Global()->Set(context.local(), v8_str("f2"), func2).FromJust());
   12903           5 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), true).ToLocalChecked();
   12904             : 
   12905             :   // Check that side effect skipping did not leak outside to future evaluations.
   12906             :   Local<Function> func3 =
   12907          10 :       Function::New(context.local(), EmptyHandler).ToLocalChecked();
   12908          25 :   CHECK(
   12909             :       context->Global()->Set(context.local(), v8_str("f3"), func3).FromJust());
   12910          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("f3()"), true).IsEmpty());
   12911             : 
   12912             :   // Check that using side effect free NewInstance works in normal evaluation
   12913             :   // (without throwOnSideEffect).
   12914          10 :   v8::debug::EvaluateGlobal(isolate, v8_str("f2()"), false).ToLocalChecked();
   12915           5 : }
   12916             : 
   12917       25880 : TEST(CallHandlerAsFunctionHasNoSideEffectNotSupported) {
   12918           5 :   v8::Isolate* isolate = CcTest::isolate();
   12919           5 :   v8::HandleScope scope(isolate);
   12920          10 :   LocalContext context;
   12921             : 
   12922             :   // Object template with call as function handler.
   12923           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   12924           5 :   templ->SetCallAsFunctionHandler(EmptyHandler);
   12925           5 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   12926          25 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   12927          10 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj()"), true).IsEmpty());
   12928             : 
   12929             :   // Side-effect-free version is not supported.
   12930             :   i::FunctionTemplateInfo cons = i::FunctionTemplateInfo::cast(
   12931           5 :       v8::Utils::OpenHandle(*templ)->constructor());
   12932           5 :   i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
   12933             :   i::CallHandlerInfo handler_info =
   12934          10 :       i::CallHandlerInfo::cast(cons->GetInstanceCallHandler());
   12935           5 :   CHECK(!handler_info->IsSideEffectFreeCallHandlerInfo());
   12936             :   handler_info->set_map(
   12937           5 :       i::ReadOnlyRoots(heap).side_effect_free_call_handler_info_map());
   12938          15 :   CHECK(v8::debug::EvaluateGlobal(isolate, v8_str("obj()"), true).IsEmpty());
   12939           5 : }
   12940             : 
   12941          12 : static void IsConstructHandler(
   12942             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   12943          12 :   ApiTestFuzzer::Fuzz();
   12944             :   args.GetReturnValue().Set(args.IsConstructCall());
   12945          12 : }
   12946             : 
   12947             : 
   12948       25881 : THREADED_TEST(IsConstructCall) {
   12949           6 :   v8::Isolate* isolate = CcTest::isolate();
   12950           6 :   v8::HandleScope scope(isolate);
   12951             : 
   12952             :   // Function template with call handler.
   12953           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12954           6 :   templ->SetCallHandler(IsConstructHandler);
   12955             : 
   12956          12 :   LocalContext context;
   12957             : 
   12958          36 :   CHECK(context->Global()
   12959             :             ->Set(context.local(), v8_str("f"),
   12960             :                   templ->GetFunction(context.local()).ToLocalChecked())
   12961             :             .FromJust());
   12962          12 :   Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
   12963           6 :   CHECK(!value->BooleanValue(isolate));
   12964          12 :   value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
   12965          12 :   CHECK(value->BooleanValue(isolate));
   12966           6 : }
   12967             : 
   12968          48 : static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
   12969          24 :   ApiTestFuzzer::Fuzz();
   12970             :   args.GetReturnValue().Set(args.NewTarget());
   12971          24 : }
   12972             : 
   12973       25881 : THREADED_TEST(NewTargetHandler) {
   12974           6 :   v8::Isolate* isolate = CcTest::isolate();
   12975           6 :   v8::HandleScope scope(isolate);
   12976             : 
   12977             :   // Function template with call handler.
   12978           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   12979           6 :   templ->SetCallHandler(NewTargetHandler);
   12980             : 
   12981          12 :   LocalContext context;
   12982             : 
   12983             :   Local<Function> function =
   12984           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   12985          30 :   CHECK(context->Global()
   12986             :             ->Set(context.local(), v8_str("f"), function)
   12987             :             .FromJust());
   12988             :   Local<Value> value = CompileRun("f()");
   12989           6 :   CHECK(value->IsUndefined());
   12990             :   value = CompileRun("new f()");
   12991           6 :   CHECK(value->IsFunction());
   12992           6 :   CHECK(value == function);
   12993             :   Local<Value> subclass = CompileRun("var g = class extends f { }; g");
   12994           6 :   CHECK(subclass->IsFunction());
   12995             :   value = CompileRun("new g()");
   12996           6 :   CHECK(value->IsFunction());
   12997           6 :   CHECK(value == subclass);
   12998             :   value = CompileRun("Reflect.construct(f, [], Array)");
   12999           6 :   CHECK(value->IsFunction());
   13000          30 :   CHECK(value ==
   13001             :         context->Global()
   13002             :             ->Get(context.local(), v8_str("Array"))
   13003           6 :             .ToLocalChecked());
   13004           6 : }
   13005             : 
   13006       25881 : THREADED_TEST(ObjectProtoToString) {
   13007           6 :   v8::Isolate* isolate = CcTest::isolate();
   13008           6 :   v8::HandleScope scope(isolate);
   13009           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13010           6 :   templ->SetClassName(v8_str("MyClass"));
   13011             : 
   13012          12 :   LocalContext context;
   13013             : 
   13014           6 :   Local<String> customized_tostring = v8_str("customized toString");
   13015             : 
   13016             :   // Replace Object.prototype.toString
   13017             :   v8_compile(
   13018             :       "Object.prototype.toString = function() {"
   13019             :       "  return 'customized toString';"
   13020             :       "}")
   13021           6 :       ->Run(context.local())
   13022           6 :       .ToLocalChecked();
   13023             : 
   13024             :   // Normal ToString call should call replaced Object.prototype.toString
   13025           6 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13026           6 :                                    .ToLocalChecked()
   13027           6 :                                    ->NewInstance(context.local())
   13028             :                                    .ToLocalChecked();
   13029           6 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13030          18 :   CHECK(value->IsString() &&
   13031             :         value->Equals(context.local(), customized_tostring).FromJust());
   13032             : 
   13033             :   // ObjectProtoToString should not call replace toString function.
   13034           6 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13035          18 :   CHECK(value->IsString() &&
   13036             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13037             : 
   13038             :   // Check global
   13039             :   value =
   13040          24 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13041          18 :   CHECK(value->IsString() &&
   13042             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13043             : 
   13044             :   // Check ordinary object
   13045             :   Local<Value> object =
   13046          12 :       v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
   13047             :   value = object.As<v8::Object>()
   13048           6 :               ->ObjectProtoToString(context.local())
   13049           6 :               .ToLocalChecked();
   13050          18 :   CHECK(value->IsString() &&
   13051           6 :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13052           6 : }
   13053             : 
   13054             : 
   13055       25880 : TEST(ObjectProtoToStringES6) {
   13056           5 :   LocalContext context;
   13057           5 :   v8::Isolate* isolate = CcTest::isolate();
   13058          10 :   v8::HandleScope scope(isolate);
   13059           5 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   13060           5 :   templ->SetClassName(v8_str("MyClass"));
   13061             : 
   13062           5 :   Local<String> customized_tostring = v8_str("customized toString");
   13063             : 
   13064             :   // Replace Object.prototype.toString
   13065             :   CompileRun(
   13066             :       "Object.prototype.toString = function() {"
   13067             :       "  return 'customized toString';"
   13068             :       "}");
   13069             : 
   13070             :   // Normal ToString call should call replaced Object.prototype.toString
   13071           5 :   Local<v8::Object> instance = templ->GetFunction(context.local())
   13072           5 :                                    .ToLocalChecked()
   13073           5 :                                    ->NewInstance(context.local())
   13074             :                                    .ToLocalChecked();
   13075           5 :   Local<String> value = instance->ToString(context.local()).ToLocalChecked();
   13076          15 :   CHECK(value->IsString() &&
   13077             :         value->Equals(context.local(), customized_tostring).FromJust());
   13078             : 
   13079             :   // ObjectProtoToString should not call replace toString function.
   13080           5 :   value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
   13081          15 :   CHECK(value->IsString() &&
   13082             :         value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
   13083             : 
   13084             :   // Check global
   13085             :   value =
   13086          20 :       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   13087          15 :   CHECK(value->IsString() &&
   13088             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13089             : 
   13090             :   // Check ordinary object
   13091             :   Local<Value> object = CompileRun("new Object()");
   13092             :   value = object.As<v8::Object>()
   13093           5 :               ->ObjectProtoToString(context.local())
   13094           5 :               .ToLocalChecked();
   13095          15 :   CHECK(value->IsString() &&
   13096             :         value->Equals(context.local(), v8_str("[object Object]")).FromJust());
   13097             : 
   13098             :   // Check that ES6 semantics using @@toStringTag work
   13099           5 :   Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
   13100             : 
   13101             : #define TEST_TOSTRINGTAG(type, tag, expected)                              \
   13102             :   do {                                                                     \
   13103             :     object = CompileRun("new " #type "()");                                \
   13104             :     CHECK(object.As<v8::Object>()                                          \
   13105             :               ->Set(context.local(), toStringTag, v8_str(#tag))            \
   13106             :               .FromJust());                                                \
   13107             :     value = object.As<v8::Object>()                                        \
   13108             :                 ->ObjectProtoToString(context.local())                     \
   13109             :                 .ToLocalChecked();                                         \
   13110             :     CHECK(value->IsString() &&                                             \
   13111             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13112             :               .FromJust());                                                \
   13113             :   } while (false)
   13114             : 
   13115          30 :   TEST_TOSTRINGTAG(Array, Object, Object);
   13116          30 :   TEST_TOSTRINGTAG(Object, Arguments, Arguments);
   13117          30 :   TEST_TOSTRINGTAG(Object, Array, Array);
   13118          30 :   TEST_TOSTRINGTAG(Object, Boolean, Boolean);
   13119          30 :   TEST_TOSTRINGTAG(Object, Date, Date);
   13120          30 :   TEST_TOSTRINGTAG(Object, Error, Error);
   13121          30 :   TEST_TOSTRINGTAG(Object, Function, Function);
   13122          30 :   TEST_TOSTRINGTAG(Object, Number, Number);
   13123          30 :   TEST_TOSTRINGTAG(Object, RegExp, RegExp);
   13124          30 :   TEST_TOSTRINGTAG(Object, String, String);
   13125          30 :   TEST_TOSTRINGTAG(Object, Foo, Foo);
   13126             : 
   13127             : #undef TEST_TOSTRINGTAG
   13128             : 
   13129             :   Local<v8::RegExp> valueRegExp =
   13130           5 :       v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
   13131           5 :           .ToLocalChecked();
   13132           5 :   Local<Value> valueNumber = v8_num(123);
   13133           5 :   Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
   13134             :   Local<v8::Function> valueFunction =
   13135             :       CompileRun("(function fn() {})").As<v8::Function>();
   13136           5 :   Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
   13137           5 :   Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
   13138           5 :   Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
   13139             : 
   13140             : #define TEST_TOSTRINGTAG(type, tagValue, expected)                         \
   13141             :   do {                                                                     \
   13142             :     object = CompileRun("new " #type "()");                                \
   13143             :     CHECK(object.As<v8::Object>()                                          \
   13144             :               ->Set(context.local(), toStringTag, tagValue)                \
   13145             :               .FromJust());                                                \
   13146             :     value = object.As<v8::Object>()                                        \
   13147             :                 ->ObjectProtoToString(context.local())                     \
   13148             :                 .ToLocalChecked();                                         \
   13149             :     CHECK(value->IsString() &&                                             \
   13150             :           value->Equals(context.local(), v8_str("[object " #expected "]")) \
   13151             :               .FromJust());                                                \
   13152             :   } while (false)
   13153             : 
   13154             : #define TEST_TOSTRINGTAG_TYPES(tagValue)                    \
   13155             :   TEST_TOSTRINGTAG(Array, tagValue, Array);                 \
   13156             :   TEST_TOSTRINGTAG(Object, tagValue, Object);               \
   13157             :   TEST_TOSTRINGTAG(Function, tagValue, Function);           \
   13158             :   TEST_TOSTRINGTAG(Date, tagValue, Date);                   \
   13159             :   TEST_TOSTRINGTAG(RegExp, tagValue, RegExp);               \
   13160             :   TEST_TOSTRINGTAG(Error, tagValue, Error);                 \
   13161             : 
   13162             :   // Test non-String-valued @@toStringTag
   13163         150 :   TEST_TOSTRINGTAG_TYPES(valueRegExp);
   13164         150 :   TEST_TOSTRINGTAG_TYPES(valueNumber);
   13165         150 :   TEST_TOSTRINGTAG_TYPES(valueSymbol);
   13166         150 :   TEST_TOSTRINGTAG_TYPES(valueFunction);
   13167         150 :   TEST_TOSTRINGTAG_TYPES(valueObject);
   13168         150 :   TEST_TOSTRINGTAG_TYPES(valueNull);
   13169         150 :   TEST_TOSTRINGTAG_TYPES(valueUndef);
   13170             : 
   13171             : #undef TEST_TOSTRINGTAG
   13172             : #undef TEST_TOSTRINGTAG_TYPES
   13173             : 
   13174             :   // @@toStringTag getter throws
   13175           5 :   Local<Value> obj = v8::Object::New(isolate);
   13176             :   obj.As<v8::Object>()
   13177          10 :       ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
   13178          10 :       .FromJust();
   13179             :   {
   13180           5 :     TryCatch try_catch(isolate);
   13181          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13182           5 :     CHECK(try_catch.HasCaught());
   13183             :   }
   13184             : 
   13185             :   // @@toStringTag getter does not throw
   13186           5 :   obj = v8::Object::New(isolate);
   13187             :   obj.As<v8::Object>()
   13188             :       ->SetAccessor(context.local(), toStringTag,
   13189          15 :                     SymbolAccessorGetterReturnsDefault, nullptr, v8_str("Test"))
   13190          10 :       .FromJust();
   13191             :   {
   13192           5 :     TryCatch try_catch(isolate);
   13193             :     value = obj.As<v8::Object>()
   13194           5 :                 ->ObjectProtoToString(context.local())
   13195           5 :                 .ToLocalChecked();
   13196          15 :     CHECK(value->IsString() &&
   13197             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13198           5 :     CHECK(!try_catch.HasCaught());
   13199             :   }
   13200             : 
   13201             :   // JS @@toStringTag value
   13202             :   obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
   13203             :   {
   13204           5 :     TryCatch try_catch(isolate);
   13205             :     value = obj.As<v8::Object>()
   13206           5 :                 ->ObjectProtoToString(context.local())
   13207           5 :                 .ToLocalChecked();
   13208          15 :     CHECK(value->IsString() &&
   13209             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13210           5 :     CHECK(!try_catch.HasCaught());
   13211             :   }
   13212             : 
   13213             :   // JS @@toStringTag getter throws
   13214             :   obj = CompileRun(
   13215             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13216             :       "  get: function() { throw 'Test'; }"
   13217             :       "}); obj");
   13218             :   {
   13219           5 :     TryCatch try_catch(isolate);
   13220          10 :     CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
   13221           5 :     CHECK(try_catch.HasCaught());
   13222             :   }
   13223             : 
   13224             :   // JS @@toStringTag getter does not throw
   13225             :   obj = CompileRun(
   13226             :       "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
   13227             :       "  get: function() { return 'Test'; }"
   13228             :       "}); obj");
   13229             :   {
   13230           5 :     TryCatch try_catch(isolate);
   13231             :     value = obj.As<v8::Object>()
   13232           5 :                 ->ObjectProtoToString(context.local())
   13233           5 :                 .ToLocalChecked();
   13234          15 :     CHECK(value->IsString() &&
   13235             :           value->Equals(context.local(), v8_str("[object Test]")).FromJust());
   13236           5 :     CHECK(!try_catch.HasCaught());
   13237           5 :   }
   13238           5 : }
   13239             : 
   13240             : 
   13241       25881 : THREADED_TEST(ObjectGetConstructorName) {
   13242           6 :   v8::Isolate* isolate = CcTest::isolate();
   13243           6 :   LocalContext context;
   13244          12 :   v8::HandleScope scope(isolate);
   13245             :   v8_compile(
   13246             :       "function Parent() {};"
   13247             :       "function Child() {};"
   13248             :       "Child.prototype = new Parent();"
   13249             :       "Child.prototype.constructor = Child;"
   13250             :       "var outer = { inner: (0, function() { }) };"
   13251             :       "var p = new Parent();"
   13252             :       "var c = new Child();"
   13253             :       "var x = new outer.inner();"
   13254             :       "var proto = Child.prototype;")
   13255           6 :       ->Run(context.local())
   13256           6 :       .ToLocalChecked();
   13257             : 
   13258             :   Local<v8::Value> p =
   13259          30 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13260          30 :   CHECK(p->IsObject() &&
   13261             :         p->ToObject(context.local())
   13262             :             .ToLocalChecked()
   13263             :             ->GetConstructorName()
   13264             :             ->Equals(context.local(), v8_str("Parent"))
   13265             :             .FromJust());
   13266             : 
   13267             :   Local<v8::Value> c =
   13268          30 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13269          30 :   CHECK(c->IsObject() &&
   13270             :         c->ToObject(context.local())
   13271             :             .ToLocalChecked()
   13272             :             ->GetConstructorName()
   13273             :             ->Equals(context.local(), v8_str("Child"))
   13274             :             .FromJust());
   13275             : 
   13276             :   Local<v8::Value> x =
   13277          30 :       context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
   13278          30 :   CHECK(x->IsObject() &&
   13279             :         x->ToObject(context.local())
   13280             :             .ToLocalChecked()
   13281             :             ->GetConstructorName()
   13282             :             ->Equals(context.local(), v8_str("outer.inner"))
   13283             :             .FromJust());
   13284             : 
   13285             :   Local<v8::Value> child_prototype =
   13286          30 :       context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
   13287          30 :   CHECK(child_prototype->IsObject() &&
   13288             :         child_prototype->ToObject(context.local())
   13289             :             .ToLocalChecked()
   13290             :             ->GetConstructorName()
   13291             :             ->Equals(context.local(), v8_str("Parent"))
   13292           6 :             .FromJust());
   13293           6 : }
   13294             : 
   13295             : 
   13296       25881 : THREADED_TEST(SubclassGetConstructorName) {
   13297           6 :   v8::Isolate* isolate = CcTest::isolate();
   13298           6 :   LocalContext context;
   13299          12 :   v8::HandleScope scope(isolate);
   13300             :   v8_compile(
   13301             :       "\"use strict\";"
   13302             :       "class Parent {}"
   13303             :       "class Child extends Parent {}"
   13304             :       "var p = new Parent();"
   13305             :       "var c = new Child();")
   13306           6 :       ->Run(context.local())
   13307           6 :       .ToLocalChecked();
   13308             : 
   13309             :   Local<v8::Value> p =
   13310          30 :       context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
   13311          30 :   CHECK(p->IsObject() &&
   13312             :         p->ToObject(context.local())
   13313             :             .ToLocalChecked()
   13314             :             ->GetConstructorName()
   13315             :             ->Equals(context.local(), v8_str("Parent"))
   13316             :             .FromJust());
   13317             : 
   13318             :   Local<v8::Value> c =
   13319          30 :       context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
   13320          30 :   CHECK(c->IsObject() &&
   13321             :         c->ToObject(context.local())
   13322             :             .ToLocalChecked()
   13323             :             ->GetConstructorName()
   13324             :             ->Equals(context.local(), v8_str("Child"))
   13325           6 :             .FromJust());
   13326           6 : }
   13327             : 
   13328             : 
   13329             : bool ApiTestFuzzer::fuzzing_ = false;
   13330       25875 : v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
   13331             : int ApiTestFuzzer::active_tests_;
   13332             : int ApiTestFuzzer::tests_being_run_;
   13333             : int ApiTestFuzzer::current_;
   13334             : 
   13335             : 
   13336             : // We are in a callback and want to switch to another thread (if we
   13337             : // are currently running the thread fuzzing test).
   13338      460722 : void ApiTestFuzzer::Fuzz() {
   13339      921444 :   if (!fuzzing_) return;
   13340       76307 :   ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
   13341       76307 :   test->ContextSwitch();
   13342             : }
   13343             : 
   13344             : 
   13345             : // Let the next thread go.  Since it is also waiting on the V8 lock it may
   13346             : // not start immediately.
   13347       76775 : bool ApiTestFuzzer::NextThread() {
   13348       76775 :   int test_position = GetNextTestNumber();
   13349       76775 :   const char* test_name = RegisterThreadedTest::nth(current_)->name();
   13350       76775 :   if (test_position == current_) {
   13351             :     if (kLogThreading)
   13352             :       printf("Stay with %s\n", test_name);
   13353             :     return false;
   13354             :   }
   13355             :   if (kLogThreading) {
   13356             :     printf("Switch from %s to %s\n",
   13357             :            test_name,
   13358             :            RegisterThreadedTest::nth(test_position)->name());
   13359             :   }
   13360       22718 :   current_ = test_position;
   13361       22718 :   RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
   13362       22718 :   return true;
   13363             : }
   13364             : 
   13365             : 
   13366         468 : void ApiTestFuzzer::Run() {
   13367             :   // When it is our turn...
   13368         468 :   gate_.Wait();
   13369             :   {
   13370             :     // ... get the V8 lock and start running the test.
   13371         468 :     v8::Locker locker(CcTest::isolate());
   13372         468 :     CallTest();
   13373             :   }
   13374             :   // This test finished.
   13375         468 :   active_ = false;
   13376         468 :   active_tests_--;
   13377             :   // If it was the last then signal that fact.
   13378         468 :   if (active_tests_ == 0) {
   13379           8 :     all_tests_done_.Signal();
   13380             :   } else {
   13381             :     // Otherwise select a new test and start that.
   13382         460 :     NextThread();
   13383             :   }
   13384         468 : }
   13385             : 
   13386             : 
   13387             : static unsigned linear_congruential_generator;
   13388             : 
   13389             : 
   13390           8 : void ApiTestFuzzer::SetUp(PartOfTest part) {
   13391           8 :   linear_congruential_generator = i::FLAG_testing_prng_seed;
   13392           8 :   fuzzing_ = true;
   13393             :   int count = RegisterThreadedTest::count();
   13394           8 :   int start =  count * part / (LAST_PART + 1);
   13395           8 :   int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
   13396           8 :   active_tests_ = tests_being_run_ = end - start + 1;
   13397         476 :   for (int i = 0; i < tests_being_run_; i++) {
   13398         468 :     RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
   13399             :   }
   13400         468 :   for (int i = 0; i < active_tests_; i++) {
   13401         468 :     RegisterThreadedTest::nth(i)->fuzzer_->Start();
   13402             :   }
   13403           8 : }
   13404             : 
   13405             : 
   13406             : static void CallTestNumber(int test_number) {
   13407         468 :   (RegisterThreadedTest::nth(test_number)->callback())();
   13408             : }
   13409             : 
   13410             : 
   13411           0 : void ApiTestFuzzer::RunAllTests() {
   13412             :   // Set off the first test.
   13413           8 :   current_ = -1;
   13414           8 :   NextThread();
   13415             :   // Wait till they are all done.
   13416           8 :   all_tests_done_.Wait();
   13417           0 : }
   13418             : 
   13419             : 
   13420       76775 : int ApiTestFuzzer::GetNextTestNumber() {
   13421             :   int next_test;
   13422     3133158 :   do {
   13423     3133158 :     next_test = (linear_congruential_generator >> 16) % tests_being_run_;
   13424     3133158 :     linear_congruential_generator *= 1664525u;
   13425     3133158 :     linear_congruential_generator += 1013904223u;
   13426     3133158 :   } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
   13427       76775 :   return next_test;
   13428             : }
   13429             : 
   13430             : 
   13431       76307 : void ApiTestFuzzer::ContextSwitch() {
   13432             :   // If the new thread is the same as the current thread there is nothing to do.
   13433       76307 :   if (NextThread()) {
   13434             :     // Now it can start.
   13435       22250 :     v8::Unlocker unlocker(CcTest::isolate());
   13436             :     // Wait till someone starts us again.
   13437       22250 :     gate_.Wait();
   13438             :     // And we're off.
   13439             :   }
   13440       76307 : }
   13441             : 
   13442             : 
   13443           8 : void ApiTestFuzzer::TearDown() {
   13444           8 :   fuzzing_ = false;
   13445        7504 :   for (int i = 0; i < RegisterThreadedTest::count(); i++) {
   13446        3744 :     ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
   13447        3744 :     if (fuzzer != nullptr) fuzzer->Join();
   13448             :   }
   13449           8 : }
   13450             : 
   13451         468 : void ApiTestFuzzer::CallTest() {
   13452         468 :   v8::Isolate::Scope scope(CcTest::isolate());
   13453             :   if (kLogThreading)
   13454             :     printf("Start test %s #%d\n",
   13455             :            RegisterThreadedTest::nth(test_number_)->name(), test_number_);
   13456         468 :   CallTestNumber(test_number_);
   13457             :   if (kLogThreading)
   13458             :     printf("End test %s #%d\n", RegisterThreadedTest::nth(test_number_)->name(),
   13459             :            test_number_);
   13460         468 : }
   13461             : 
   13462             : #define THREADING_TEST(INDEX, NAME)            \
   13463             :   TEST(Threading##INDEX) {                     \
   13464             :     ApiTestFuzzer::SetUp(ApiTestFuzzer::NAME); \
   13465             :     ApiTestFuzzer::RunAllTests();              \
   13466             :     ApiTestFuzzer::TearDown();                 \
   13467             :   }
   13468             : 
   13469       25877 : THREADING_TEST(1, FIRST_PART)
   13470       25877 : THREADING_TEST(2, SECOND_PART)
   13471       25877 : THREADING_TEST(3, THIRD_PART)
   13472       25877 : THREADING_TEST(4, FOURTH_PART)
   13473       25877 : THREADING_TEST(5, FIFTH_PART)
   13474       25877 : THREADING_TEST(6, SIXTH_PART)
   13475       25877 : THREADING_TEST(7, SEVENTH_PART)
   13476       25877 : THREADING_TEST(8, EIGHTH_PART)
   13477             : 
   13478             : #undef THREADING_TEST
   13479             : 
   13480          10 : static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13481             :   v8::Isolate* isolate = args.GetIsolate();
   13482           5 :   CHECK(v8::Locker::IsLocked(isolate));
   13483           5 :   ApiTestFuzzer::Fuzz();
   13484             :   v8::Unlocker unlocker(isolate);
   13485             :   const char* code = "throw 7;";
   13486             :   {
   13487             :     v8::Locker nested_locker(isolate);
   13488          10 :     v8::HandleScope scope(isolate);
   13489             :     v8::Local<Value> exception;
   13490             :     {
   13491           5 :       v8::TryCatch try_catch(isolate);
   13492             :       v8::Local<Value> value = CompileRun(code);
   13493           5 :       CHECK(value.IsEmpty());
   13494           5 :       CHECK(try_catch.HasCaught());
   13495             :       // Make sure to wrap the exception in a new handle because
   13496             :       // the handle returned from the TryCatch is destroyed
   13497             :       // when the TryCatch is destroyed.
   13498          10 :       exception = Local<Value>::New(isolate, try_catch.Exception());
   13499             :     }
   13500          10 :     args.GetIsolate()->ThrowException(exception);
   13501           5 :   }
   13502           5 : }
   13503             : 
   13504             : 
   13505          15 : static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13506           5 :   CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13507           5 :   ApiTestFuzzer::Fuzz();
   13508           5 :   v8::Unlocker unlocker(CcTest::isolate());
   13509             :   const char* code = "throw 7;";
   13510             :   {
   13511           5 :     v8::Locker nested_locker(CcTest::isolate());
   13512          10 :     v8::HandleScope scope(args.GetIsolate());
   13513             :     v8::Local<Value> value = CompileRun(code);
   13514           5 :     CHECK(value.IsEmpty());
   13515          10 :     args.GetReturnValue().Set(v8_str("foo"));
   13516           5 :   }
   13517           5 : }
   13518             : 
   13519             : 
   13520             : // These are locking tests that don't need to be run again
   13521             : // as part of the locking aggregation tests.
   13522       25880 : TEST(NestedLockers) {
   13523           5 :   v8::Isolate* isolate = CcTest::isolate();
   13524             :   v8::Locker locker(isolate);
   13525           5 :   CHECK(v8::Locker::IsLocked(isolate));
   13526          10 :   LocalContext env;
   13527          10 :   v8::HandleScope scope(env->GetIsolate());
   13528             :   Local<v8::FunctionTemplate> fun_templ =
   13529           5 :       v8::FunctionTemplate::New(isolate, ThrowInJS);
   13530          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13531          25 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13532             :   Local<Script> script = v8_compile("(function () {"
   13533             :                                     "  try {"
   13534             :                                     "    throw_in_js();"
   13535             :                                     "    return 42;"
   13536             :                                     "  } catch (e) {"
   13537             :                                     "    return e * 13;"
   13538             :                                     "  }"
   13539             :                                     "})();");
   13540          15 :   CHECK_EQ(91, script->Run(env.local())
   13541             :                    .ToLocalChecked()
   13542             :                    ->Int32Value(env.local())
   13543           5 :                    .FromJust());
   13544           5 : }
   13545             : 
   13546             : 
   13547             : // These are locking tests that don't need to be run again
   13548             : // as part of the locking aggregation tests.
   13549       25880 : TEST(NestedLockersNoTryCatch) {
   13550           5 :   v8::Locker locker(CcTest::isolate());
   13551          10 :   LocalContext env;
   13552          10 :   v8::HandleScope scope(env->GetIsolate());
   13553             :   Local<v8::FunctionTemplate> fun_templ =
   13554           5 :       v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
   13555          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13556          25 :   CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
   13557             :   Local<Script> script = v8_compile("(function () {"
   13558             :                                     "  try {"
   13559             :                                     "    throw_in_js();"
   13560             :                                     "    return 42;"
   13561             :                                     "  } catch (e) {"
   13562             :                                     "    return e * 13;"
   13563             :                                     "  }"
   13564             :                                     "})();");
   13565          15 :   CHECK_EQ(91, script->Run(env.local())
   13566             :                    .ToLocalChecked()
   13567             :                    ->Int32Value(env.local())
   13568           5 :                    .FromJust());
   13569           5 : }
   13570             : 
   13571             : 
   13572       25881 : THREADED_TEST(RecursiveLocking) {
   13573           6 :   v8::Locker locker(CcTest::isolate());
   13574             :   {
   13575           6 :     v8::Locker locker2(CcTest::isolate());
   13576           6 :     CHECK(v8::Locker::IsLocked(CcTest::isolate()));
   13577           6 :   }
   13578           6 : }
   13579             : 
   13580             : 
   13581          12 : static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
   13582          12 :   ApiTestFuzzer::Fuzz();
   13583          24 :   v8::Unlocker unlocker(CcTest::isolate());
   13584          12 : }
   13585             : 
   13586             : 
   13587       25881 : THREADED_TEST(LockUnlockLock) {
   13588             :   {
   13589           6 :     v8::Locker locker(CcTest::isolate());
   13590          12 :     v8::HandleScope scope(CcTest::isolate());
   13591          12 :     LocalContext env;
   13592             :     Local<v8::FunctionTemplate> fun_templ =
   13593           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13594          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13595          30 :     CHECK(env->Global()
   13596             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13597             :               .FromJust());
   13598             :     Local<Script> script = v8_compile("(function () {"
   13599             :                                       "  unlock_for_a_moment();"
   13600             :                                       "  return 42;"
   13601             :                                       "})();");
   13602          18 :     CHECK_EQ(42, script->Run(env.local())
   13603             :                      .ToLocalChecked()
   13604             :                      ->Int32Value(env.local())
   13605           6 :                      .FromJust());
   13606             :   }
   13607             :   {
   13608           6 :     v8::Locker locker(CcTest::isolate());
   13609          12 :     v8::HandleScope scope(CcTest::isolate());
   13610          12 :     LocalContext env;
   13611             :     Local<v8::FunctionTemplate> fun_templ =
   13612           6 :         v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
   13613          12 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   13614          30 :     CHECK(env->Global()
   13615             :               ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
   13616             :               .FromJust());
   13617             :     Local<Script> script = v8_compile("(function () {"
   13618             :                                       "  unlock_for_a_moment();"
   13619             :                                       "  return 42;"
   13620             :                                       "})();");
   13621          18 :     CHECK_EQ(42, script->Run(env.local())
   13622             :                      .ToLocalChecked()
   13623             :                      ->Int32Value(env.local())
   13624           6 :                      .FromJust());
   13625             :   }
   13626           6 : }
   13627             : 
   13628             : 
   13629         130 : static int GetGlobalObjectsCount() {
   13630             :   int count = 0;
   13631         130 :   i::HeapIterator it(CcTest::heap());
   13632     1400958 :   for (i::HeapObject object = it.next(); !object.is_null();
   13633             :        object = it.next()) {
   13634      700349 :     if (object->IsJSGlobalObject()) {
   13635          30 :       i::JSGlobalObject g = i::JSGlobalObject::cast(object);
   13636             :       // Skip dummy global object.
   13637          30 :       if (g->global_dictionary()->NumberOfElements() != 0) {
   13638          30 :         count++;
   13639             :       }
   13640             :     }
   13641             :   }
   13642         130 :   return count;
   13643             : }
   13644             : 
   13645             : 
   13646         100 : static void CheckSurvivingGlobalObjectsCount(int expected) {
   13647             :   // We need to collect all garbage twice to be sure that everything
   13648             :   // has been collected.  This is because inline caches are cleared in
   13649             :   // the first garbage collection but some of the maps have already
   13650             :   // been marked at that point.  Therefore some of the maps are not
   13651             :   // collected until the second garbage collection.
   13652         100 :   CcTest::CollectAllGarbage();
   13653         100 :   CcTest::CollectAllGarbage();
   13654         100 :   int count = GetGlobalObjectsCount();
   13655         100 :   CHECK_EQ(expected, count);
   13656         100 : }
   13657             : 
   13658             : 
   13659       25880 : TEST(DontLeakGlobalObjects) {
   13660             :   // Regression test for issues 1139850 and 1174891.
   13661             : 
   13662           5 :   i::FLAG_expose_gc = true;
   13663           5 :   v8::V8::Initialize();
   13664             : 
   13665          30 :   for (int i = 0; i < 5; i++) {
   13666          25 :     { v8::HandleScope scope(CcTest::isolate());
   13667          25 :       LocalContext context;
   13668             :     }
   13669          25 :     CcTest::isolate()->ContextDisposedNotification();
   13670          25 :     CheckSurvivingGlobalObjectsCount(0);
   13671             : 
   13672          25 :     { v8::HandleScope scope(CcTest::isolate());
   13673          50 :       LocalContext context;
   13674          75 :       v8_compile("Date")->Run(context.local()).ToLocalChecked();
   13675             :     }
   13676          25 :     CcTest::isolate()->ContextDisposedNotification();
   13677          25 :     CheckSurvivingGlobalObjectsCount(0);
   13678             : 
   13679          25 :     { v8::HandleScope scope(CcTest::isolate());
   13680          50 :       LocalContext context;
   13681          75 :       v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
   13682             :     }
   13683          25 :     CcTest::isolate()->ContextDisposedNotification();
   13684          25 :     CheckSurvivingGlobalObjectsCount(0);
   13685             : 
   13686          25 :     { v8::HandleScope scope(CcTest::isolate());
   13687          25 :       const char* extension_list[] = { "v8/gc" };
   13688             :       v8::ExtensionConfiguration extensions(1, extension_list);
   13689          50 :       LocalContext context(&extensions);
   13690          75 :       v8_compile("gc();")->Run(context.local()).ToLocalChecked();
   13691             :     }
   13692          25 :     CcTest::isolate()->ContextDisposedNotification();
   13693          25 :     CheckSurvivingGlobalObjectsCount(0);
   13694             :   }
   13695           5 : }
   13696             : 
   13697             : 
   13698       25880 : TEST(CopyablePersistent) {
   13699           5 :   LocalContext context;
   13700           5 :   v8::Isolate* isolate = context->GetIsolate();
   13701          25 :   i::GlobalHandles* globals =
   13702             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13703             :   size_t initial_handles = globals->handles_count();
   13704             :   typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
   13705             :       CopyableObject;
   13706             :   {
   13707             :     CopyableObject handle1;
   13708             :     {
   13709           5 :       v8::HandleScope scope(isolate);
   13710          10 :       handle1.Reset(isolate, v8::Object::New(isolate));
   13711             :     }
   13712           5 :     CHECK_EQ(initial_handles + 1, globals->handles_count());
   13713             :     CopyableObject  handle2;
   13714             :     handle2 = handle1;
   13715           5 :     CHECK(handle1 == handle2);
   13716           5 :     CHECK_EQ(initial_handles + 2, globals->handles_count());
   13717             :     CopyableObject handle3(handle2);
   13718           5 :     CHECK(handle1 == handle3);
   13719           5 :     CHECK_EQ(initial_handles + 3, globals->handles_count());
   13720             :   }
   13721             :   // Verify autodispose
   13722           5 :   CHECK_EQ(initial_handles, globals->handles_count());
   13723           5 : }
   13724             : 
   13725             : 
   13726           5 : static void WeakApiCallback(
   13727          10 :     const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
   13728             :   data.GetParameter()->Reset();
   13729           5 :   delete data.GetParameter();
   13730           5 : }
   13731             : 
   13732             : 
   13733       25880 : TEST(WeakCallbackApi) {
   13734           5 :   LocalContext context;
   13735           5 :   v8::Isolate* isolate = context->GetIsolate();
   13736          10 :   i::GlobalHandles* globals =
   13737             :       reinterpret_cast<i::Isolate*>(isolate)->global_handles();
   13738             :   size_t initial_handles = globals->handles_count();
   13739             :   {
   13740           5 :     v8::HandleScope scope(isolate);
   13741           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   13742          25 :     CHECK(
   13743             :         obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
   13744             :             .FromJust());
   13745             :     v8::Persistent<v8::Object>* handle =
   13746           5 :         new v8::Persistent<v8::Object>(isolate, obj);
   13747             :     handle->SetWeak<v8::Persistent<v8::Object>>(
   13748           5 :         handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
   13749             :   }
   13750           5 :   CcTest::PreciseCollectAllGarbage();
   13751             :   // Verify disposed.
   13752           5 :   CHECK_EQ(initial_handles, globals->handles_count());
   13753           5 : }
   13754             : 
   13755             : 
   13756       25875 : v8::Persistent<v8::Object> some_object;
   13757       25875 : v8::Persistent<v8::Object> bad_handle;
   13758             : 
   13759             : 
   13760           6 : void NewPersistentHandleCallback2(
   13761          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13762           6 :   v8::HandleScope scope(data.GetIsolate());
   13763           6 :   bad_handle.Reset(data.GetIsolate(), some_object);
   13764           6 : }
   13765             : 
   13766             : 
   13767           6 : void NewPersistentHandleCallback1(
   13768          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13769             :   data.GetParameter()->Reset();
   13770             :   data.SetSecondPassCallback(NewPersistentHandleCallback2);
   13771           6 : }
   13772             : 
   13773             : 
   13774       25881 : THREADED_TEST(NewPersistentHandleFromWeakCallback) {
   13775           6 :   LocalContext context;
   13776           6 :   v8::Isolate* isolate = context->GetIsolate();
   13777             : 
   13778             :   v8::Persistent<v8::Object> handle1, handle2;
   13779             :   {
   13780           6 :     v8::HandleScope scope(isolate);
   13781          12 :     some_object.Reset(isolate, v8::Object::New(isolate));
   13782          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   13783          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   13784             :   }
   13785             :   // Note: order is implementation dependent alas: currently
   13786             :   // global handle nodes are processed by PostGarbageCollectionProcessing
   13787             :   // in reverse allocation order, so if second allocated handle is deleted,
   13788             :   // weak callback of the first handle would be able to 'reallocate' it.
   13789             :   handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
   13790             :                   v8::WeakCallbackType::kParameter);
   13791             :   handle2.Reset();
   13792           6 :   CcTest::CollectAllGarbage();
   13793           6 : }
   13794             : 
   13795             : 
   13796       25875 : v8::Persistent<v8::Object> to_be_disposed;
   13797             : 
   13798             : 
   13799           6 : void DisposeAndForceGcCallback2(
   13800             :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13801             :   to_be_disposed.Reset();
   13802           6 :   CcTest::CollectAllGarbage();
   13803           6 : }
   13804             : 
   13805             : 
   13806           6 : void DisposeAndForceGcCallback1(
   13807          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13808             :   data.GetParameter()->Reset();
   13809             :   data.SetSecondPassCallback(DisposeAndForceGcCallback2);
   13810           6 : }
   13811             : 
   13812             : 
   13813       25881 : THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
   13814           6 :   LocalContext context;
   13815           6 :   v8::Isolate* isolate = context->GetIsolate();
   13816             : 
   13817             :   v8::Persistent<v8::Object> handle1, handle2;
   13818             :   {
   13819           6 :     v8::HandleScope scope(isolate);
   13820          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   13821          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   13822             :   }
   13823             :   handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
   13824             :                   v8::WeakCallbackType::kParameter);
   13825             :   to_be_disposed.Reset(isolate, handle2);
   13826           6 :   CcTest::CollectAllGarbage();
   13827           6 : }
   13828             : 
   13829           6 : void DisposingCallback(
   13830           6 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13831             :   data.GetParameter()->Reset();
   13832           6 : }
   13833             : 
   13834           6 : void HandleCreatingCallback2(
   13835          18 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13836           6 :   v8::HandleScope scope(data.GetIsolate());
   13837          12 :   v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
   13838           6 : }
   13839             : 
   13840             : 
   13841           6 : void HandleCreatingCallback1(
   13842          12 :     const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
   13843             :   data.GetParameter()->Reset();
   13844             :   data.SetSecondPassCallback(HandleCreatingCallback2);
   13845           6 : }
   13846             : 
   13847             : 
   13848       25881 : THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
   13849           6 :   v8::Locker locker(CcTest::isolate());
   13850          12 :   LocalContext context;
   13851           6 :   v8::Isolate* isolate = context->GetIsolate();
   13852             : 
   13853             :   v8::Persistent<v8::Object> handle1, handle2, handle3;
   13854             :   {
   13855           6 :     v8::HandleScope scope(isolate);
   13856          12 :     handle3.Reset(isolate, v8::Object::New(isolate));
   13857          12 :     handle2.Reset(isolate, v8::Object::New(isolate));
   13858          12 :     handle1.Reset(isolate, v8::Object::New(isolate));
   13859             :   }
   13860             :   handle2.SetWeak(&handle2, DisposingCallback,
   13861             :                   v8::WeakCallbackType::kParameter);
   13862             :   handle3.SetWeak(&handle3, HandleCreatingCallback1,
   13863             :                   v8::WeakCallbackType::kParameter);
   13864           6 :   CcTest::CollectAllGarbage();
   13865          12 :   EmptyMessageQueues(isolate);
   13866           6 : }
   13867             : 
   13868             : 
   13869       25881 : THREADED_TEST(CheckForCrossContextObjectLiterals) {
   13870           6 :   v8::V8::Initialize();
   13871             : 
   13872             :   const int nof = 2;
   13873             :   const char* sources[nof] = {
   13874             :     "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
   13875             :     "Object()"
   13876           6 :   };
   13877             : 
   13878          18 :   for (int i = 0; i < nof; i++) {
   13879          12 :     const char* source = sources[i];
   13880          12 :     { v8::HandleScope scope(CcTest::isolate());
   13881          24 :       LocalContext context;
   13882          12 :       CompileRun(source);
   13883             :     }
   13884          12 :     { v8::HandleScope scope(CcTest::isolate());
   13885          24 :       LocalContext context;
   13886          12 :       CompileRun(source);
   13887             :     }
   13888             :   }
   13889           6 : }
   13890             : 
   13891             : 
   13892           6 : static v8::Local<Value> NestedScope(v8::Local<Context> env) {
   13893           6 :   v8::EscapableHandleScope inner(env->GetIsolate());
   13894           6 :   env->Enter();
   13895           6 :   v8::Local<Value> three = v8_num(3);
   13896             :   v8::Local<Value> value = inner.Escape(three);
   13897           6 :   env->Exit();
   13898          12 :   return value;
   13899             : }
   13900             : 
   13901             : 
   13902       25881 : THREADED_TEST(NestedHandleScopeAndContexts) {
   13903           6 :   v8::Isolate* isolate = CcTest::isolate();
   13904           6 :   v8::HandleScope outer(isolate);
   13905           6 :   v8::Local<Context> env = Context::New(isolate);
   13906           6 :   env->Enter();
   13907           6 :   v8::Local<Value> value = NestedScope(env);
   13908           6 :   v8::Local<String> str(value->ToString(env).ToLocalChecked());
   13909           6 :   CHECK(!str.IsEmpty());
   13910           6 :   env->Exit();
   13911           6 : }
   13912             : 
   13913             : static v8::base::HashMap* code_map = nullptr;
   13914             : static v8::base::HashMap* jitcode_line_info = nullptr;
   13915             : static int saw_bar = 0;
   13916             : static int move_events = 0;
   13917             : 
   13918             : 
   13919        5361 : static bool FunctionNameIs(const char* expected,
   13920             :                            const v8::JitCodeEvent* event) {
   13921             :   // Log lines for functions are of the general form:
   13922             :   // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
   13923             :   // where the type is one of "*", "~" or "".
   13924             :   static const char* kPreamble;
   13925        5361 :   if (!i::FLAG_lazy) {
   13926           0 :     kPreamble = "Function:";
   13927             :   } else {
   13928        5361 :     kPreamble = "LazyCompile:";
   13929             :   }
   13930        5361 :   static size_t kPreambleLen = strlen(kPreamble);
   13931             : 
   13932       10667 :   if (event->name.len < kPreambleLen ||
   13933        5306 :       strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
   13934             :     return false;
   13935             :   }
   13936             : 
   13937         153 :   const char* tail = event->name.str + kPreambleLen;
   13938         153 :   size_t tail_len = event->name.len - kPreambleLen;
   13939         153 :   size_t expected_len = strlen(expected);
   13940         153 :   if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
   13941         148 :     --tail_len;
   13942         148 :     ++tail;
   13943             :   }
   13944             : 
   13945             :   // Check for tails like 'bar :1'.
   13946         285 :   if (tail_len > expected_len + 2 &&
   13947         264 :       tail[expected_len] == ' ' &&
   13948         264 :       tail[expected_len + 1] == ':' &&
   13949         264 :       tail[expected_len + 2] &&
   13950         132 :       !strncmp(tail, expected, expected_len)) {
   13951             :     return true;
   13952             :   }
   13953             : 
   13954          87 :   if (tail_len != expected_len)
   13955             :     return false;
   13956             : 
   13957          21 :   return strncmp(tail, expected, expected_len) == 0;
   13958             : }
   13959             : 
   13960             : 
   13961        7688 : static void event_handler(const v8::JitCodeEvent* event) {
   13962        7688 :   CHECK_NOT_NULL(event);
   13963        7688 :   CHECK_NOT_NULL(code_map);
   13964        7688 :   CHECK_NOT_NULL(jitcode_line_info);
   13965             : 
   13966             :   class DummyJitCodeLineInfo {
   13967             :   };
   13968             : 
   13969        7688 :   switch (event->type) {
   13970             :     case v8::JitCodeEvent::CODE_ADDED: {
   13971        5361 :       CHECK_NOT_NULL(event->code_start);
   13972        5361 :       CHECK_NE(0, static_cast<int>(event->code_len));
   13973        5361 :       CHECK_NOT_NULL(event->name.str);
   13974             :       v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
   13975        5361 :           event->code_start, i::ComputePointerHash(event->code_start));
   13976        5361 :       entry->value = reinterpret_cast<void*>(event->code_len);
   13977             : 
   13978        5361 :       if (FunctionNameIs("bar", event)) {
   13979          66 :         ++saw_bar;
   13980             :         }
   13981             :       }
   13982             :       break;
   13983             : 
   13984             :     case v8::JitCodeEvent::CODE_MOVED: {
   13985         197 :         uint32_t hash = i::ComputePointerHash(event->code_start);
   13986             :         // We would like to never see code move that we haven't seen before,
   13987             :         // but the code creation event does not happen until the line endings
   13988             :         // have been calculated (this is so that we can report the line in the
   13989             :         // script at which the function source is found, see
   13990             :         // Compiler::RecordFunctionCompilation) and the line endings
   13991             :         // calculations can cause a GC, which can move the newly created code
   13992             :         // before its existence can be logged.
   13993             :         v8::base::HashMap::Entry* entry =
   13994         197 :             code_map->Lookup(event->code_start, hash);
   13995         197 :         if (entry != nullptr) {
   13996         197 :           ++move_events;
   13997             : 
   13998         197 :           CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
   13999         197 :           code_map->Remove(event->code_start, hash);
   14000             : 
   14001             :           entry = code_map->LookupOrInsert(
   14002             :               event->new_code_start,
   14003         394 :               i::ComputePointerHash(event->new_code_start));
   14004         197 :           entry->value = reinterpret_cast<void*>(event->code_len);
   14005             :         }
   14006             :       }
   14007             :       break;
   14008             : 
   14009             :     case v8::JitCodeEvent::CODE_REMOVED:
   14010             :       // Object/code removal events are currently not dispatched from the GC.
   14011           0 :       UNREACHABLE();
   14012             : 
   14013             :     // For CODE_START_LINE_INFO_RECORDING event, we will create one
   14014             :     // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
   14015             :     // record it in jitcode_line_info.
   14016             :     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
   14017         180 :         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
   14018             :         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
   14019         180 :         temp_event->user_data = line_info;
   14020             :         v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
   14021         360 :             line_info, i::ComputePointerHash(line_info));
   14022         180 :         entry->value = reinterpret_cast<void*>(line_info);
   14023             :       }
   14024         180 :       break;
   14025             :     // For these two events, we will check whether the event->user_data
   14026             :     // data structure is created before during CODE_START_LINE_INFO_RECORDING
   14027             :     // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
   14028             :     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
   14029         180 :       CHECK_NOT_NULL(event->user_data);
   14030             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14031             :       v8::base::HashMap::Entry* entry =
   14032         180 :           jitcode_line_info->Lookup(event->user_data, hash);
   14033         180 :       CHECK_NOT_NULL(entry);
   14034         180 :       delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
   14035             :       }
   14036         180 :       break;
   14037             : 
   14038             :     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
   14039        1770 :       CHECK_NOT_NULL(event->user_data);
   14040             :       uint32_t hash = i::ComputePointerHash(event->user_data);
   14041             :       v8::base::HashMap::Entry* entry =
   14042        1770 :           jitcode_line_info->Lookup(event->user_data, hash);
   14043        1770 :       CHECK_NOT_NULL(entry);
   14044             :       }
   14045             :       break;
   14046             : 
   14047             :     default:
   14048             :       // Impossible event.
   14049           0 :       UNREACHABLE();
   14050             :   }
   14051        7688 : }
   14052             : 
   14053             : 
   14054       25880 : UNINITIALIZED_TEST(SetJitCodeEventHandler) {
   14055           5 :   i::FLAG_stress_compaction = true;
   14056           5 :   i::FLAG_incremental_marking = false;
   14057           5 :   if (i::FLAG_never_compact) return;
   14058             :   const char* script =
   14059             :       "function bar() {"
   14060             :       "  var sum = 0;"
   14061             :       "  for (i = 0; i < 10; ++i)"
   14062             :       "    sum = foo(i);"
   14063             :       "  return sum;"
   14064             :       "}"
   14065             :       "function foo(i) { return i; };"
   14066             :       "bar();";
   14067             : 
   14068             :   // Run this test in a new isolate to make sure we don't
   14069             :   // have remnants of state from other code.
   14070             :   v8::Isolate::CreateParams create_params;
   14071           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   14072          55 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   14073           5 :   isolate->Enter();
   14074             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   14075           5 :   i::Heap* heap = i_isolate->heap();
   14076             : 
   14077             :   // Start with a clean slate.
   14078           5 :   heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14079             : 
   14080             :   {
   14081           5 :     v8::HandleScope scope(isolate);
   14082             :     v8::base::HashMap code;
   14083           5 :     code_map = &code;
   14084             : 
   14085             :     v8::base::HashMap lineinfo;
   14086           5 :     jitcode_line_info = &lineinfo;
   14087             : 
   14088           5 :     saw_bar = 0;
   14089           5 :     move_events = 0;
   14090             : 
   14091           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
   14092             : 
   14093             :     // Generate new code objects sparsely distributed across several
   14094             :     // different fragmented code-space pages.
   14095             :     const int kIterations = 10;
   14096          55 :     for (int i = 0; i < kIterations; ++i) {
   14097             :       LocalContext env(isolate);
   14098             :       i::AlwaysAllocateScope always_allocate(i_isolate);
   14099             :       CompileRun(script);
   14100             : 
   14101             :       // Keep a strong reference to the code object in the handle scope.
   14102             :       i::Handle<i::JSFunction> bar(i::Handle<i::JSFunction>::cast(
   14103             :           v8::Utils::OpenHandle(*env->Global()
   14104         200 :                                      ->Get(env.local(), v8_str("bar"))
   14105         100 :                                      .ToLocalChecked())));
   14106             :       i::Handle<i::JSFunction> foo(i::Handle<i::JSFunction>::cast(
   14107             :           v8::Utils::OpenHandle(*env->Global()
   14108         200 :                                      ->Get(env.local(), v8_str("foo"))
   14109         100 :                                      .ToLocalChecked())));
   14110             : 
   14111             :       i::PagedSpace* foo_owning_space = reinterpret_cast<i::PagedSpace*>(
   14112         100 :           i::Page::FromHeapObject(foo->abstract_code())->owner());
   14113             :       i::PagedSpace* bar_owning_space = reinterpret_cast<i::PagedSpace*>(
   14114         100 :           i::Page::FromHeapObject(bar->abstract_code())->owner());
   14115          50 :       CHECK_EQ(foo_owning_space, bar_owning_space);
   14116          50 :       i::heap::SimulateFullSpace(foo_owning_space);
   14117             : 
   14118             :       // Clear the compilation cache to get more wastage.
   14119          50 :       reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
   14120          50 :     }
   14121             : 
   14122             :     // Force code movement.
   14123           5 :     heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
   14124             : 
   14125           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14126             : 
   14127           5 :     CHECK_LE(kIterations, saw_bar);
   14128           5 :     CHECK_LT(0, move_events);
   14129             : 
   14130           5 :     code_map = nullptr;
   14131          10 :     jitcode_line_info = nullptr;
   14132             :   }
   14133             : 
   14134           5 :   isolate->Exit();
   14135           5 :   isolate->Dispose();
   14136             : 
   14137             :   // Do this in a new isolate.
   14138           5 :   isolate = v8::Isolate::New(create_params);
   14139           5 :   isolate->Enter();
   14140             : 
   14141             :   // Verify that we get callbacks for existing code objects when we
   14142             :   // request enumeration of existing code.
   14143             :   {
   14144           5 :     v8::HandleScope scope(isolate);
   14145           5 :     LocalContext env(isolate);
   14146             :     CompileRun(script);
   14147             : 
   14148             :     // Now get code through initial iteration.
   14149             :     v8::base::HashMap code;
   14150           5 :     code_map = &code;
   14151             : 
   14152             :     v8::base::HashMap lineinfo;
   14153           5 :     jitcode_line_info = &lineinfo;
   14154             : 
   14155             :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
   14156           5 :                                     event_handler);
   14157           5 :     isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, nullptr);
   14158             : 
   14159           5 :     jitcode_line_info = nullptr;
   14160             :     // We expect that we got some events. Note that if we could get code removal
   14161             :     // notifications, we could compare two collections, one created by listening
   14162             :     // from the time of creation of an isolate, and the other by subscribing
   14163             :     // with EnumExisting.
   14164           5 :     CHECK_LT(0u, code.occupancy());
   14165             : 
   14166          10 :     code_map = nullptr;
   14167             :   }
   14168             : 
   14169           5 :   isolate->Exit();
   14170           5 :   isolate->Dispose();
   14171             : }
   14172             : 
   14173       25880 : TEST(ExternalAllocatedMemory) {
   14174           5 :   v8::Isolate* isolate = CcTest::isolate();
   14175           5 :   v8::HandleScope outer(isolate);
   14176           5 :   v8::Local<Context> env(Context::New(isolate));
   14177           5 :   CHECK(!env.IsEmpty());
   14178             :   const int64_t kSize = 1024*1024;
   14179             :   int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
   14180           5 :   CHECK_EQ(baseline + kSize,
   14181             :            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   14182           5 :   CHECK_EQ(baseline,
   14183             :            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
   14184             :   const int64_t kTriggerGCSize =
   14185           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14186           5 :   CHECK_EQ(baseline + kTriggerGCSize,
   14187             :            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   14188          10 :   CHECK_EQ(baseline,
   14189           5 :            isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
   14190           5 : }
   14191             : 
   14192             : 
   14193       25880 : TEST(Regress51719) {
   14194           5 :   i::FLAG_incremental_marking = false;
   14195           5 :   CcTest::InitializeVM();
   14196             : 
   14197             :   const int64_t kTriggerGCSize =
   14198           5 :       CcTest::i_isolate()->heap()->external_memory_hard_limit() + 1;
   14199           5 :   v8::Isolate* isolate = CcTest::isolate();
   14200             :   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
   14201           5 : }
   14202             : 
   14203             : // Regression test for issue 54, object templates with embedder fields
   14204             : // but no accessors or interceptors did not get their embedder field
   14205             : // count set on instances.
   14206       25881 : THREADED_TEST(Regress54) {
   14207           6 :   LocalContext context;
   14208           6 :   v8::Isolate* isolate = context->GetIsolate();
   14209          12 :   v8::HandleScope outer(isolate);
   14210          12 :   static v8::Persistent<v8::ObjectTemplate> templ;
   14211           6 :   if (templ.IsEmpty()) {
   14212           6 :     v8::EscapableHandleScope inner(isolate);
   14213           6 :     v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
   14214           6 :     local->SetInternalFieldCount(1);
   14215             :     templ.Reset(isolate, inner.Escape(local));
   14216             :   }
   14217             :   v8::Local<v8::Object> result =
   14218             :       v8::Local<v8::ObjectTemplate>::New(isolate, templ)
   14219           6 :           ->NewInstance(context.local())
   14220           6 :           .ToLocalChecked();
   14221          12 :   CHECK_EQ(1, result->InternalFieldCount());
   14222           6 : }
   14223             : 
   14224             : 
   14225             : // If part of the threaded tests, this test makes ThreadingTest fail
   14226             : // on mac.
   14227       25880 : TEST(CatchStackOverflow) {
   14228           5 :   LocalContext context;
   14229          10 :   v8::HandleScope scope(context->GetIsolate());
   14230          10 :   v8::TryCatch try_catch(context->GetIsolate());
   14231             :   v8::Local<v8::Value> result = CompileRun(
   14232             :       "function f() {"
   14233             :       "  return f();"
   14234             :       "}"
   14235             :       ""
   14236             :       "f();");
   14237          10 :   CHECK(result.IsEmpty());
   14238           5 : }
   14239             : 
   14240             : 
   14241          18 : static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
   14242             :                                     const char* resource_name,
   14243             :                                     int line_offset) {
   14244          18 :   v8::HandleScope scope(CcTest::isolate());
   14245          36 :   v8::TryCatch try_catch(CcTest::isolate());
   14246          18 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   14247          36 :   CHECK(script->Run(context).IsEmpty());
   14248          18 :   CHECK(try_catch.HasCaught());
   14249          18 :   v8::Local<v8::Message> message = try_catch.Message();
   14250          18 :   CHECK(!message.IsEmpty());
   14251          36 :   CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
   14252          18 :   CHECK_EQ(91, message->GetStartPosition());
   14253          18 :   CHECK_EQ(92, message->GetEndPosition());
   14254          36 :   CHECK_EQ(2, message->GetStartColumn(context).FromJust());
   14255          36 :   CHECK_EQ(3, message->GetEndColumn(context).FromJust());
   14256             :   v8::String::Utf8Value line(CcTest::isolate(),
   14257          54 :                              message->GetSourceLine(context).ToLocalChecked());
   14258          18 :   CHECK_EQ(0, strcmp("  throw 'nirk';", *line));
   14259             :   v8::String::Utf8Value name(CcTest::isolate(),
   14260          36 :                              message->GetScriptOrigin().ResourceName());
   14261          36 :   CHECK_EQ(0, strcmp(resource_name, *name));
   14262          18 : }
   14263             : 
   14264             : 
   14265       25881 : THREADED_TEST(TryCatchSourceInfo) {
   14266           6 :   LocalContext context;
   14267          12 :   v8::HandleScope scope(context->GetIsolate());
   14268             :   v8::Local<v8::String> source = v8_str(
   14269             :       "function Foo() {\n"
   14270             :       "  return Bar();\n"
   14271             :       "}\n"
   14272             :       "\n"
   14273             :       "function Bar() {\n"
   14274             :       "  return Baz();\n"
   14275             :       "}\n"
   14276             :       "\n"
   14277             :       "function Baz() {\n"
   14278             :       "  throw 'nirk';\n"
   14279             :       "}\n"
   14280             :       "\n"
   14281           6 :       "Foo();\n");
   14282             : 
   14283             :   const char* resource_name;
   14284             :   v8::Local<v8::Script> script;
   14285             :   resource_name = "test.js";
   14286           6 :   script = CompileWithOrigin(source, resource_name);
   14287           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14288             : 
   14289             :   resource_name = "test1.js";
   14290           6 :   v8::ScriptOrigin origin1(v8_str(resource_name));
   14291             :   script =
   14292          12 :       v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
   14293           6 :   CheckTryCatchSourceInfo(script, resource_name, 0);
   14294             : 
   14295             :   resource_name = "test2.js";
   14296             :   v8::ScriptOrigin origin2(v8_str(resource_name),
   14297           6 :                            v8::Integer::New(context->GetIsolate(), 7));
   14298             :   script =
   14299          12 :       v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
   14300          12 :   CheckTryCatchSourceInfo(script, resource_name, 7);
   14301           6 : }
   14302             : 
   14303             : 
   14304       25881 : THREADED_TEST(TryCatchSourceInfoForEOSError) {
   14305           6 :   LocalContext context;
   14306          12 :   v8::HandleScope scope(context->GetIsolate());
   14307          12 :   v8::TryCatch try_catch(context->GetIsolate());
   14308          12 :   CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
   14309           6 :   CHECK(try_catch.HasCaught());
   14310           6 :   v8::Local<v8::Message> message = try_catch.Message();
   14311          12 :   CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   14312          18 :   CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
   14313           6 : }
   14314             : 
   14315             : 
   14316       25881 : THREADED_TEST(CompilationCache) {
   14317           6 :   LocalContext context;
   14318          12 :   v8::HandleScope scope(context->GetIsolate());
   14319           6 :   v8::Local<v8::String> source0 = v8_str("1234");
   14320           6 :   v8::Local<v8::String> source1 = v8_str("1234");
   14321             :   v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
   14322             :   v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
   14323           6 :   v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
   14324           6 :                                       .ToLocalChecked();  // different origin
   14325          18 :   CHECK_EQ(1234, script0->Run(context.local())
   14326             :                      .ToLocalChecked()
   14327             :                      ->Int32Value(context.local())
   14328             :                      .FromJust());
   14329          18 :   CHECK_EQ(1234, script1->Run(context.local())
   14330             :                      .ToLocalChecked()
   14331             :                      ->Int32Value(context.local())
   14332             :                      .FromJust());
   14333          18 :   CHECK_EQ(1234, script2->Run(context.local())
   14334             :                      .ToLocalChecked()
   14335             :                      ->Int32Value(context.local())
   14336           6 :                      .FromJust());
   14337           6 : }
   14338             : 
   14339             : 
   14340           0 : static void FunctionNameCallback(
   14341           0 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   14342           0 :   ApiTestFuzzer::Fuzz();
   14343           0 :   args.GetReturnValue().Set(v8_num(42));
   14344           0 : }
   14345             : 
   14346             : 
   14347       25881 : THREADED_TEST(CallbackFunctionName) {
   14348           6 :   LocalContext context;
   14349           6 :   v8::Isolate* isolate = context->GetIsolate();
   14350          12 :   v8::HandleScope scope(isolate);
   14351           6 :   Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
   14352             :   t->Set(v8_str("asdf"),
   14353          18 :          v8::FunctionTemplate::New(isolate, FunctionNameCallback));
   14354          36 :   CHECK(context->Global()
   14355             :             ->Set(context.local(), v8_str("obj"),
   14356             :                   t->NewInstance(context.local()).ToLocalChecked())
   14357             :             .FromJust());
   14358             :   v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
   14359           6 :   CHECK(value->IsString());
   14360          12 :   v8::String::Utf8Value name(isolate, value);
   14361          12 :   CHECK_EQ(0, strcmp("asdf", *name));
   14362           6 : }
   14363             : 
   14364             : 
   14365       25881 : THREADED_TEST(DateAccess) {
   14366           6 :   LocalContext context;
   14367          12 :   v8::HandleScope scope(context->GetIsolate());
   14368             :   v8::Local<v8::Value> date =
   14369           6 :       v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
   14370           6 :   CHECK(date->IsDate());
   14371          12 :   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
   14372           6 : }
   14373             : 
   14374          48 : void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   14375             :                      unsigned index, const char* name) {
   14376          48 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14377             :   v8::Local<v8::Value> value =
   14378          96 :       properties->Get(context, v8::Integer::New(isolate, index))
   14379          48 :           .ToLocalChecked();
   14380          48 :   CHECK(value->IsSymbol());
   14381             :   v8::String::Utf8Value symbol_name(isolate,
   14382          48 :                                     Local<Symbol>::Cast(value)->Name());
   14383          48 :   if (strcmp(name, *symbol_name) != 0) {
   14384             :     FATAL("properties[%u] was Symbol('%s') instead of Symbol('%s').", index,
   14385           0 :           name, *symbol_name);
   14386          48 :   }
   14387          48 : }
   14388             : 
   14389         150 : void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
   14390             :                       unsigned length, const char* names[]) {
   14391         150 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14392         150 :   CHECK_EQ(length, properties->Length());
   14393         924 :   for (unsigned i = 0; i < length; i++) {
   14394             :     v8::Local<v8::Value> value =
   14395        2772 :         properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
   14396         924 :     if (names[i] == nullptr) {
   14397             :       DCHECK(value->IsSymbol());
   14398             :     } else {
   14399         876 :       v8::String::Utf8Value elm(isolate, value);
   14400         876 :       if (strcmp(names[i], *elm) != 0) {
   14401           0 :         FATAL("properties[%u] was '%s' instead of '%s'.", i, *elm, names[i]);
   14402         876 :       }
   14403             :     }
   14404             :   }
   14405         150 : }
   14406             : 
   14407          42 : void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   14408             :                      unsigned length, const char* names[]) {
   14409          42 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14410             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   14411          84 :   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
   14412          42 :   CheckStringArray(isolate, props, length, names);
   14413          42 : }
   14414             : 
   14415             : 
   14416          24 : void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
   14417             :                         unsigned elmc, const char* elmv[]) {
   14418          24 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   14419             :   v8::Local<v8::Object> obj = val.As<v8::Object>();
   14420             :   v8::Local<v8::Array> props =
   14421          24 :       obj->GetOwnPropertyNames(context).ToLocalChecked();
   14422          24 :   CHECK_EQ(elmc, props->Length());
   14423          42 :   for (unsigned i = 0; i < elmc; i++) {
   14424             :     v8::String::Utf8Value elm(
   14425             :         isolate,
   14426         126 :         props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
   14427          42 :     CHECK_EQ(0, strcmp(elmv[i], *elm));
   14428          42 :   }
   14429          24 : }
   14430             : 
   14431             : 
   14432       25881 : THREADED_TEST(PropertyEnumeration) {
   14433           6 :   LocalContext context;
   14434           6 :   v8::Isolate* isolate = context->GetIsolate();
   14435          12 :   v8::HandleScope scope(isolate);
   14436             :   v8::Local<v8::Value> obj = CompileRun(
   14437             :       "var result = [];"
   14438             :       "result[0] = {};"
   14439             :       "result[1] = {a: 1, b: 2};"
   14440             :       "result[2] = [1, 2, 3];"
   14441             :       "var proto = {x: 1, y: 2, z: 3};"
   14442             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   14443             :       "result[3] = x;"
   14444             :       "result[4] = {21350:1};"
   14445             :       "x = Object.create(null);"
   14446             :       "x.a = 1; x[12345678] = 1;"
   14447             :       "result[5] = x;"
   14448             :       "result;");
   14449             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   14450           6 :   CHECK_EQ(6u, elms->Length());
   14451             :   int elmc0 = 0;
   14452             :   const char** elmv0 = nullptr;
   14453             :   CheckProperties(
   14454             :       isolate,
   14455          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14456          12 :       elmc0, elmv0);
   14457             :   CheckOwnProperties(
   14458             :       isolate,
   14459          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14460          12 :       elmc0, elmv0);
   14461             :   int elmc1 = 2;
   14462           6 :   const char* elmv1[] = {"a", "b"};
   14463             :   CheckProperties(
   14464             :       isolate,
   14465          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   14466          12 :       elmc1, elmv1);
   14467             :   CheckOwnProperties(
   14468             :       isolate,
   14469          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
   14470          12 :       elmc1, elmv1);
   14471             :   int elmc2 = 3;
   14472           6 :   const char* elmv2[] = {"0", "1", "2"};
   14473             :   CheckProperties(
   14474             :       isolate,
   14475          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   14476          12 :       elmc2, elmv2);
   14477             :   CheckOwnProperties(
   14478             :       isolate,
   14479          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
   14480          12 :       elmc2, elmv2);
   14481             :   int elmc3 = 4;
   14482           6 :   const char* elmv3[] = {"w", "z", "x", "y"};
   14483             :   CheckProperties(
   14484             :       isolate,
   14485          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   14486          12 :       elmc3, elmv3);
   14487             :   int elmc4 = 2;
   14488           6 :   const char* elmv4[] = {"w", "z"};
   14489             :   CheckOwnProperties(
   14490             :       isolate,
   14491          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
   14492          12 :       elmc4, elmv4);
   14493             :   // Dictionary elements.
   14494             :   int elmc5 = 1;
   14495           6 :   const char* elmv5[] = {"21350"};
   14496             :   CheckProperties(
   14497             :       isolate,
   14498          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 4)).ToLocalChecked(),
   14499          12 :       elmc5, elmv5);
   14500             :   // Dictionary properties.
   14501             :   int elmc6 = 2;
   14502           6 :   const char* elmv6[] = {"12345678", "a"};
   14503             :   CheckProperties(
   14504             :       isolate,
   14505          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 5)).ToLocalChecked(),
   14506          18 :       elmc6, elmv6);
   14507           6 : }
   14508             : 
   14509             : 
   14510       25881 : THREADED_TEST(PropertyEnumeration2) {
   14511           6 :   LocalContext context;
   14512           6 :   v8::Isolate* isolate = context->GetIsolate();
   14513          12 :   v8::HandleScope scope(isolate);
   14514             :   v8::Local<v8::Value> obj = CompileRun(
   14515             :       "var result = [];"
   14516             :       "result[0] = {};"
   14517             :       "result[1] = {a: 1, b: 2};"
   14518             :       "result[2] = [1, 2, 3];"
   14519             :       "var proto = {x: 1, y: 2, z: 3};"
   14520             :       "var x = { __proto__: proto, w: 0, z: 1 };"
   14521             :       "result[3] = x;"
   14522             :       "result;");
   14523             :   v8::Local<v8::Array> elms = obj.As<v8::Array>();
   14524           6 :   CHECK_EQ(4u, elms->Length());
   14525             :   int elmc0 = 0;
   14526             :   const char** elmv0 = nullptr;
   14527             :   CheckProperties(
   14528             :       isolate,
   14529          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
   14530          12 :       elmc0, elmv0);
   14531             : 
   14532             :   v8::Local<v8::Value> val =
   14533          18 :       elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
   14534             :   v8::Local<v8::Array> props =
   14535           6 :       val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
   14536           6 :   CHECK_EQ(0u, props->Length());
   14537           0 :   for (uint32_t i = 0; i < props->Length(); i++) {
   14538             :     printf("p[%u]\n", i);
   14539           6 :   }
   14540           6 : }
   14541             : 
   14542       25881 : THREADED_TEST(GetPropertyNames) {
   14543           6 :   LocalContext context;
   14544           6 :   v8::Isolate* isolate = context->GetIsolate();
   14545          12 :   v8::HandleScope scope(isolate);
   14546             :   v8::Local<v8::Value> result = CompileRun(
   14547             :       "var result = {0: 0, 1: 1, a: 2, b: 3};"
   14548             :       "result[2**32] = '4294967296';"
   14549             :       "result[2**32-1] = '4294967295';"
   14550             :       "result[2**32-2] = '4294967294';"
   14551             :       "result[Symbol('symbol')] = true;"
   14552             :       "result.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
   14553             :       "result;");
   14554             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   14555             :   v8::PropertyFilter default_filter =
   14556             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   14557             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   14558             : 
   14559             :   v8::Local<v8::Array> properties =
   14560          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   14561             :   const char* expected_properties1[] = {"0", "1",          "4294967294", "a",
   14562             :                                         "b", "4294967296", "4294967295", "2",
   14563           6 :                                         "3", "c",          "d"};
   14564           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14565             : 
   14566             :   properties =
   14567             :       object
   14568             :           ->GetPropertyNames(context.local(),
   14569             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14570           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14571          12 :           .ToLocalChecked();
   14572           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14573             : 
   14574             :   properties = object
   14575             :                    ->GetPropertyNames(context.local(),
   14576             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14577             :                                       include_symbols_filter,
   14578           6 :                                       v8::IndexFilter::kIncludeIndices)
   14579          12 :                    .ToLocalChecked();
   14580             :   const char* expected_properties1_1[] = {
   14581             :       "0",          "1",     "4294967294", "a", "b", "4294967296",
   14582           6 :       "4294967295", nullptr, "2",          "3", "c", "d"};
   14583           6 :   CheckStringArray(isolate, properties, 12, expected_properties1_1);
   14584           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14585             : 
   14586             :   properties =
   14587             :       object
   14588             :           ->GetPropertyNames(context.local(),
   14589             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14590           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   14591          12 :           .ToLocalChecked();
   14592             :   const char* expected_properties2[] = {"a",          "b", "4294967296",
   14593           6 :                                         "4294967295", "c", "d"};
   14594           6 :   CheckStringArray(isolate, properties, 6, expected_properties2);
   14595             : 
   14596             :   properties = object
   14597             :                    ->GetPropertyNames(context.local(),
   14598             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14599             :                                       include_symbols_filter,
   14600           6 :                                       v8::IndexFilter::kSkipIndices)
   14601          12 :                    .ToLocalChecked();
   14602             :   const char* expected_properties2_1[] = {
   14603           6 :       "a", "b", "4294967296", "4294967295", nullptr, "c", "d"};
   14604           6 :   CheckStringArray(isolate, properties, 7, expected_properties2_1);
   14605           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14606             : 
   14607             :   properties =
   14608             :       object
   14609             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14610           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14611          12 :           .ToLocalChecked();
   14612             :   const char* expected_properties3[] = {
   14613             :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295",
   14614           6 :   };
   14615           6 :   CheckStringArray(isolate, properties, 7, expected_properties3);
   14616             : 
   14617             :   properties = object
   14618             :                    ->GetPropertyNames(
   14619             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14620           6 :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   14621          12 :                    .ToLocalChecked();
   14622             :   const char* expected_properties3_1[] = {
   14623           6 :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295", nullptr};
   14624           6 :   CheckStringArray(isolate, properties, 8, expected_properties3_1);
   14625           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14626             : 
   14627             :   properties =
   14628             :       object
   14629             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14630           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   14631          12 :           .ToLocalChecked();
   14632           6 :   const char* expected_properties4[] = {"a", "b", "4294967296", "4294967295"};
   14633           6 :   CheckStringArray(isolate, properties, 4, expected_properties4);
   14634             : 
   14635             :   properties = object
   14636             :                    ->GetPropertyNames(
   14637             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14638           6 :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   14639          12 :                    .ToLocalChecked();
   14640             :   const char* expected_properties4_1[] = {"a", "b", "4294967296", "4294967295",
   14641           6 :                                           nullptr};
   14642           6 :   CheckStringArray(isolate, properties, 5, expected_properties4_1);
   14643          12 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14644           6 : }
   14645             : 
   14646       25881 : THREADED_TEST(ProxyGetPropertyNames) {
   14647           6 :   LocalContext context;
   14648           6 :   v8::Isolate* isolate = context->GetIsolate();
   14649          12 :   v8::HandleScope scope(isolate);
   14650             :   v8::Local<v8::Value> result = CompileRun(
   14651             :       "var target = {0: 0, 1: 1, a: 2, b: 3};"
   14652             :       "target[2**32] = '4294967296';"
   14653             :       "target[2**32-1] = '4294967295';"
   14654             :       "target[2**32-2] = '4294967294';"
   14655             :       "target[Symbol('symbol')] = true;"
   14656             :       "target.__proto__ = {__proto__:null, 2: 4, 3: 5, c: 6, d: 7};"
   14657             :       "var result = new Proxy(target, {});"
   14658             :       "result;");
   14659             :   v8::Local<v8::Object> object = result.As<v8::Object>();
   14660             :   v8::PropertyFilter default_filter =
   14661             :       static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
   14662             :   v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
   14663             : 
   14664             :   v8::Local<v8::Array> properties =
   14665          12 :       object->GetPropertyNames(context.local()).ToLocalChecked();
   14666             :   const char* expected_properties1[] = {"0", "1",          "4294967294", "a",
   14667             :                                         "b", "4294967296", "4294967295", "2",
   14668           6 :                                         "3", "c",          "d"};
   14669           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14670             : 
   14671             :   properties =
   14672             :       object
   14673             :           ->GetPropertyNames(context.local(),
   14674             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14675           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14676          12 :           .ToLocalChecked();
   14677           6 :   CheckStringArray(isolate, properties, 11, expected_properties1);
   14678             : 
   14679             :   properties = object
   14680             :                    ->GetPropertyNames(context.local(),
   14681             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14682             :                                       include_symbols_filter,
   14683           6 :                                       v8::IndexFilter::kIncludeIndices)
   14684          12 :                    .ToLocalChecked();
   14685             :   const char* expected_properties1_1[] = {
   14686             :       "0",          "1",     "4294967294", "a", "b", "4294967296",
   14687           6 :       "4294967295", nullptr, "2",          "3", "c", "d"};
   14688           6 :   CheckStringArray(isolate, properties, 12, expected_properties1_1);
   14689           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14690             : 
   14691             :   properties =
   14692             :       object
   14693             :           ->GetPropertyNames(context.local(),
   14694             :                              v8::KeyCollectionMode::kIncludePrototypes,
   14695           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   14696          12 :           .ToLocalChecked();
   14697             :   const char* expected_properties2[] = {"a",          "b", "4294967296",
   14698           6 :                                         "4294967295", "c", "d"};
   14699           6 :   CheckStringArray(isolate, properties, 6, expected_properties2);
   14700             : 
   14701             :   properties = object
   14702             :                    ->GetPropertyNames(context.local(),
   14703             :                                       v8::KeyCollectionMode::kIncludePrototypes,
   14704             :                                       include_symbols_filter,
   14705           6 :                                       v8::IndexFilter::kSkipIndices)
   14706          12 :                    .ToLocalChecked();
   14707             :   const char* expected_properties2_1[] = {
   14708           6 :       "a", "b", "4294967296", "4294967295", nullptr, "c", "d"};
   14709           6 :   CheckStringArray(isolate, properties, 7, expected_properties2_1);
   14710           6 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14711             : 
   14712             :   properties =
   14713             :       object
   14714             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14715           6 :                              default_filter, v8::IndexFilter::kIncludeIndices)
   14716          12 :           .ToLocalChecked();
   14717             :   const char* expected_properties3[] = {"0", "1",          "4294967294", "a",
   14718           6 :                                         "b", "4294967296", "4294967295"};
   14719           6 :   CheckStringArray(isolate, properties, 7, expected_properties3);
   14720             : 
   14721             :   properties = object
   14722             :                    ->GetPropertyNames(
   14723             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14724           6 :                        include_symbols_filter, v8::IndexFilter::kIncludeIndices)
   14725          12 :                    .ToLocalChecked();
   14726             :   const char* expected_properties3_1[] = {
   14727           6 :       "0", "1", "4294967294", "a", "b", "4294967296", "4294967295", nullptr};
   14728           6 :   CheckStringArray(isolate, properties, 8, expected_properties3_1);
   14729           6 :   CheckIsSymbolAt(isolate, properties, 7, "symbol");
   14730             : 
   14731             :   properties =
   14732             :       object
   14733             :           ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
   14734           6 :                              default_filter, v8::IndexFilter::kSkipIndices)
   14735          12 :           .ToLocalChecked();
   14736           6 :   const char* expected_properties4[] = {"a", "b", "4294967296", "4294967295"};
   14737           6 :   CheckStringArray(isolate, properties, 4, expected_properties4);
   14738             : 
   14739             :   properties = object
   14740             :                    ->GetPropertyNames(
   14741             :                        context.local(), v8::KeyCollectionMode::kOwnOnly,
   14742           6 :                        include_symbols_filter, v8::IndexFilter::kSkipIndices)
   14743          12 :                    .ToLocalChecked();
   14744             :   const char* expected_properties4_1[] = {"a", "b", "4294967296", "4294967295",
   14745           6 :                                           nullptr};
   14746           6 :   CheckStringArray(isolate, properties, 5, expected_properties4_1);
   14747          12 :   CheckIsSymbolAt(isolate, properties, 4, "symbol");
   14748           6 : }
   14749             : 
   14750       25881 : THREADED_TEST(AccessChecksReenabledCorrectly) {
   14751           6 :   LocalContext context;
   14752           6 :   v8::Isolate* isolate = context->GetIsolate();
   14753          12 :   v8::HandleScope scope(isolate);
   14754           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   14755           6 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   14756          18 :   templ->Set(v8_str("a"), v8_str("a"));
   14757             :   // Add more than 8 (see kMaxFastProperties) properties
   14758             :   // so that the constructor will force copying map.
   14759             :   // Cannot sprintf, gcc complains unsafety.
   14760             :   char buf[4];
   14761          66 :   for (char i = '0'; i <= '9' ; i++) {
   14762          60 :     buf[0] = i;
   14763         660 :     for (char j = '0'; j <= '9'; j++) {
   14764         600 :       buf[1] = j;
   14765        6600 :       for (char k = '0'; k <= '9'; k++) {
   14766        6000 :         buf[2] = k;
   14767        6000 :         buf[3] = 0;
   14768       18000 :         templ->Set(v8_str(buf), v8::Number::New(isolate, k));
   14769             :       }
   14770             :     }
   14771             :   }
   14772             : 
   14773             :   Local<v8::Object> instance_1 =
   14774           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   14775          30 :   CHECK(context->Global()
   14776             :             ->Set(context.local(), v8_str("obj_1"), instance_1)
   14777             :             .FromJust());
   14778             : 
   14779             :   Local<Value> value_1 = CompileRun("obj_1.a");
   14780           6 :   CHECK(value_1.IsEmpty());
   14781             : 
   14782             :   Local<v8::Object> instance_2 =
   14783           6 :       templ->NewInstance(context.local()).ToLocalChecked();
   14784          30 :   CHECK(context->Global()
   14785             :             ->Set(context.local(), v8_str("obj_2"), instance_2)
   14786             :             .FromJust());
   14787             : 
   14788             :   Local<Value> value_2 = CompileRun("obj_2.a");
   14789          12 :   CHECK(value_2.IsEmpty());
   14790           6 : }
   14791             : 
   14792             : 
   14793             : // This tests that we do not allow dictionary load/call inline caches
   14794             : // to use functions that have not yet been compiled.  The potential
   14795             : // problem of loading a function that has not yet been compiled can
   14796             : // arise because we share code between contexts via the compilation
   14797             : // cache.
   14798       25881 : THREADED_TEST(DictionaryICLoadedFunction) {
   14799           6 :   v8::HandleScope scope(CcTest::isolate());
   14800             :   // Test LoadIC.
   14801          18 :   for (int i = 0; i < 2; i++) {
   14802          12 :     LocalContext context;
   14803          72 :     CHECK(context->Global()
   14804             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   14805             :               .FromJust());
   14806          60 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   14807             :     CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
   14808          12 :   }
   14809             :   // Test CallIC.
   14810          12 :   for (int i = 0; i < 2; i++) {
   14811          12 :     LocalContext context;
   14812          72 :     CHECK(context->Global()
   14813             :               ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
   14814             :               .FromJust());
   14815          60 :     context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
   14816             :     CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
   14817          18 :   }
   14818           6 : }
   14819             : 
   14820             : 
   14821             : // Test that cross-context new calls use the context of the callee to
   14822             : // create the new JavaScript object.
   14823       25881 : THREADED_TEST(CrossContextNew) {
   14824           6 :   v8::Isolate* isolate = CcTest::isolate();
   14825           6 :   v8::HandleScope scope(isolate);
   14826           6 :   v8::Local<Context> context0 = Context::New(isolate);
   14827           6 :   v8::Local<Context> context1 = Context::New(isolate);
   14828             : 
   14829             :   // Allow cross-domain access.
   14830           6 :   Local<String> token = v8_str("<security token>");
   14831           6 :   context0->SetSecurityToken(token);
   14832           6 :   context1->SetSecurityToken(token);
   14833             : 
   14834             :   // Set an 'x' property on the Object prototype and define a
   14835             :   // constructor function in context0.
   14836           6 :   context0->Enter();
   14837             :   CompileRun("Object.prototype.x = 42; function C() {};");
   14838           6 :   context0->Exit();
   14839             : 
   14840             :   // Call the constructor function from context0 and check that the
   14841             :   // result has the 'x' property.
   14842           6 :   context1->Enter();
   14843          30 :   CHECK(context1->Global()
   14844             :             ->Set(context1, v8_str("other"), context0->Global())
   14845             :             .FromJust());
   14846             :   Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
   14847           6 :   CHECK(value->IsInt32());
   14848          12 :   CHECK_EQ(42, value->Int32Value(context1).FromJust());
   14849           6 :   context1->Exit();
   14850           6 : }
   14851             : 
   14852             : 
   14853             : // Verify that we can clone an object
   14854       25880 : TEST(ObjectClone) {
   14855           5 :   LocalContext env;
   14856           5 :   v8::Isolate* isolate = env->GetIsolate();
   14857          10 :   v8::HandleScope scope(isolate);
   14858             : 
   14859             :   const char* sample =
   14860             :     "var rv = {};"      \
   14861             :     "rv.alpha = 'hello';" \
   14862             :     "rv.beta = 123;"     \
   14863             :     "rv;";
   14864             : 
   14865             :   // Create an object, verify basics.
   14866             :   Local<Value> val = CompileRun(sample);
   14867           5 :   CHECK(val->IsObject());
   14868             :   Local<v8::Object> obj = val.As<v8::Object>();
   14869          20 :   obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
   14870             : 
   14871          25 :   CHECK(v8_str("hello")
   14872             :             ->Equals(env.local(),
   14873             :                      obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   14874             :             .FromJust());
   14875          25 :   CHECK(v8::Integer::New(isolate, 123)
   14876             :             ->Equals(env.local(),
   14877             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14878             :             .FromJust());
   14879          25 :   CHECK(v8_str("cloneme")
   14880             :             ->Equals(env.local(),
   14881             :                      obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   14882             :             .FromJust());
   14883             : 
   14884             :   // Clone it.
   14885           5 :   Local<v8::Object> clone = obj->Clone();
   14886          25 :   CHECK(v8_str("hello")
   14887             :             ->Equals(env.local(),
   14888             :                      clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
   14889             :             .FromJust());
   14890          25 :   CHECK(v8::Integer::New(isolate, 123)
   14891             :             ->Equals(env.local(),
   14892             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14893             :             .FromJust());
   14894          25 :   CHECK(v8_str("cloneme")
   14895             :             ->Equals(env.local(),
   14896             :                      clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
   14897             :             .FromJust());
   14898             : 
   14899             :   // Set a property on the clone, verify each object.
   14900          20 :   CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
   14901             :             .FromJust());
   14902          25 :   CHECK(v8::Integer::New(isolate, 123)
   14903             :             ->Equals(env.local(),
   14904             :                      obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14905             :             .FromJust());
   14906          25 :   CHECK(v8::Integer::New(isolate, 456)
   14907             :             ->Equals(env.local(),
   14908             :                      clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
   14909           5 :             .FromJust());
   14910           5 : }
   14911             : 
   14912             : 
   14913             : class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
   14914             :  public:
   14915             :   explicit OneByteVectorResource(i::Vector<const char> vector)
   14916           6 :       : data_(vector) {}
   14917           6 :   ~OneByteVectorResource() override = default;
   14918          48 :   size_t length() const override { return data_.length(); }
   14919          24 :   const char* data() const override { return data_.start(); }
   14920           0 :   void Dispose() override {}
   14921             : 
   14922             :  private:
   14923             :   i::Vector<const char> data_;
   14924             : };
   14925             : 
   14926             : 
   14927             : class UC16VectorResource : public v8::String::ExternalStringResource {
   14928             :  public:
   14929             :   explicit UC16VectorResource(i::Vector<const i::uc16> vector)
   14930          10 :       : data_(vector) {}
   14931           6 :   ~UC16VectorResource() override = default;
   14932          24 :   size_t length() const override { return data_.length(); }
   14933         414 :   const i::uc16* data() const override { return data_.start(); }
   14934           0 :   void Dispose() override {}
   14935             : 
   14936             :  private:
   14937             :   i::Vector<const i::uc16> data_;
   14938             : };
   14939             : 
   14940          12 : static void MorphAString(i::String string,
   14941             :                          OneByteVectorResource* one_byte_resource,
   14942             :                          UC16VectorResource* uc16_resource) {
   14943             :   i::Isolate* isolate = CcTest::i_isolate();
   14944          12 :   CHECK(i::StringShape(string).IsExternal());
   14945          12 :   i::ReadOnlyRoots roots(CcTest::heap());
   14946          12 :   if (string->IsOneByteRepresentation()) {
   14947             :     // Check old map is not internalized or long.
   14948          12 :     CHECK(string->map() == roots.external_one_byte_string_map());
   14949             :     // Morph external string to be TwoByte string.
   14950          12 :     string->set_map(roots.external_string_map());
   14951          12 :     i::ExternalTwoByteString morphed = i::ExternalTwoByteString::cast(string);
   14952          12 :     CcTest::heap()->UpdateExternalString(morphed, string->length(), 0);
   14953          12 :     morphed->SetResource(isolate, uc16_resource);
   14954             :   } else {
   14955             :     // Check old map is not internalized or long.
   14956           0 :     CHECK(string->map() == roots.external_string_map());
   14957             :     // Morph external string to be one-byte string.
   14958           0 :     string->set_map(roots.external_one_byte_string_map());
   14959           0 :     i::ExternalOneByteString morphed = i::ExternalOneByteString::cast(string);
   14960           0 :     CcTest::heap()->UpdateExternalString(morphed, string->length(), 0);
   14961           0 :     morphed->SetResource(isolate, one_byte_resource);
   14962             :   }
   14963          12 : }
   14964             : 
   14965             : // Test that we can still flatten a string if the components it is built up
   14966             : // from have been turned into 16 bit strings in the mean time.
   14967       25881 : THREADED_TEST(MorphCompositeStringTest) {
   14968             :   char utf_buffer[129];
   14969             :   const char* c_string = "Now is the time for all good men"
   14970             :                          " to come to the aid of the party";
   14971           6 :   uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
   14972             :   {
   14973           6 :     LocalContext env;
   14974             :     i::Factory* factory = CcTest::i_isolate()->factory();
   14975           6 :     v8::Isolate* isolate = env->GetIsolate();
   14976             :     i::Isolate* i_isolate = CcTest::i_isolate();
   14977          12 :     v8::HandleScope scope(isolate);
   14978             :     OneByteVectorResource one_byte_resource(
   14979             :         i::Vector<const char>(c_string, i::StrLength(c_string)));
   14980             :     UC16VectorResource uc16_resource(
   14981             :         i::Vector<const uint16_t>(two_byte_string, i::StrLength(c_string)));
   14982             : 
   14983             :     Local<String> lhs(v8::Utils::ToLocal(
   14984             :         factory->NewExternalStringFromOneByte(&one_byte_resource)
   14985          12 :             .ToHandleChecked()));
   14986             :     Local<String> rhs(v8::Utils::ToLocal(
   14987             :         factory->NewExternalStringFromOneByte(&one_byte_resource)
   14988          12 :             .ToHandleChecked()));
   14989             : 
   14990          30 :     CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
   14991          30 :     CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
   14992             : 
   14993             :     CompileRun(
   14994             :         "var cons = lhs + rhs;"
   14995             :         "var slice = lhs.substring(1, lhs.length - 1);"
   14996             :         "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
   14997             : 
   14998           6 :     CHECK(lhs->IsOneByte());
   14999           6 :     CHECK(rhs->IsOneByte());
   15000             : 
   15001           6 :     i::String ilhs = *v8::Utils::OpenHandle(*lhs);
   15002           6 :     i::String irhs = *v8::Utils::OpenHandle(*rhs);
   15003           6 :     MorphAString(ilhs, &one_byte_resource, &uc16_resource);
   15004           6 :     MorphAString(irhs, &one_byte_resource, &uc16_resource);
   15005             : 
   15006             :     // This should UTF-8 without flattening, since everything is ASCII.
   15007             :     Local<String> cons =
   15008          12 :         v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
   15009           6 :     CHECK_EQ(128, cons->Utf8Length(isolate));
   15010           6 :     int nchars = -1;
   15011           6 :     CHECK_EQ(129, cons->WriteUtf8(isolate, utf_buffer, -1, &nchars));
   15012           6 :     CHECK_EQ(128, nchars);
   15013           6 :     CHECK_EQ(0, strcmp(
   15014             :         utf_buffer,
   15015             :         "Now is the time for all good men to come to the aid of the party"
   15016             :         "Now is the time for all good men to come to the aid of the party"));
   15017             : 
   15018             :     // Now do some stuff to make sure the strings are flattened, etc.
   15019             :     CompileRun(
   15020             :         "/[^a-z]/.test(cons);"
   15021             :         "/[^a-z]/.test(slice);"
   15022             :         "/[^a-z]/.test(slice_on_cons);");
   15023             :     const char* expected_cons =
   15024             :         "Now is the time for all good men to come to the aid of the party"
   15025             :         "Now is the time for all good men to come to the aid of the party";
   15026             :     const char* expected_slice =
   15027             :         "ow is the time for all good men to come to the aid of the part";
   15028             :     const char* expected_slice_on_cons =
   15029             :         "ow is the time for all good men to come to the aid of the party"
   15030             :         "Now is the time for all good men to come to the aid of the part";
   15031          42 :     CHECK(v8_str(expected_cons)
   15032             :               ->Equals(env.local(), env->Global()
   15033             :                                         ->Get(env.local(), v8_str("cons"))
   15034             :                                         .ToLocalChecked())
   15035             :               .FromJust());
   15036          42 :     CHECK(v8_str(expected_slice)
   15037             :               ->Equals(env.local(), env->Global()
   15038             :                                         ->Get(env.local(), v8_str("slice"))
   15039             :                                         .ToLocalChecked())
   15040             :               .FromJust());
   15041          42 :     CHECK(v8_str(expected_slice_on_cons)
   15042             :               ->Equals(env.local(),
   15043             :                        env->Global()
   15044             :                            ->Get(env.local(), v8_str("slice_on_cons"))
   15045             :                            .ToLocalChecked())
   15046             :               .FromJust());
   15047             : 
   15048             :     // This avoids the GC from trying to free a stack allocated resource.
   15049           6 :     if (ilhs->IsExternalOneByteString())
   15050           0 :       i::ExternalOneByteString::cast(ilhs)->SetResource(i_isolate, nullptr);
   15051             :     else
   15052           6 :       i::ExternalTwoByteString::cast(ilhs)->SetResource(i_isolate, nullptr);
   15053           6 :     if (irhs->IsExternalOneByteString())
   15054           0 :       i::ExternalOneByteString::cast(irhs)->SetResource(i_isolate, nullptr);
   15055             :     else
   15056          12 :       i::ExternalTwoByteString::cast(irhs)->SetResource(i_isolate, nullptr);
   15057             :   }
   15058             :   i::DeleteArray(two_byte_string);
   15059           6 : }
   15060             : 
   15061             : 
   15062       25880 : TEST(CompileExternalTwoByteSource) {
   15063           5 :   LocalContext context;
   15064          10 :   v8::HandleScope scope(context->GetIsolate());
   15065             : 
   15066             :   // This is a very short list of sources, which currently is to check for a
   15067             :   // regression caused by r2703.
   15068             :   const char* one_byte_sources[] = {
   15069             :       "0.5",
   15070             :       "-0.5",   // This mainly testes PushBack in the Scanner.
   15071             :       "--0.5",  // This mainly testes PushBack in the Scanner.
   15072           5 :       nullptr};
   15073             : 
   15074             :   // Compile the sources as external two byte strings.
   15075          20 :   for (int i = 0; one_byte_sources[i] != nullptr; i++) {
   15076          15 :     uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
   15077          15 :     TestResource* uc16_resource = new TestResource(two_byte_string);
   15078             :     v8::Local<v8::String> source =
   15079          15 :         v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
   15080          30 :             .ToLocalChecked();
   15081          15 :     v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
   15082           5 :   }
   15083           5 : }
   15084             : 
   15085       25875 : struct RegExpInterruptionData {
   15086             :   v8::base::Atomic32 loop_count;
   15087             :   UC16VectorResource* string_resource;
   15088             :   v8::Persistent<v8::String> string;
   15089       25875 : } regexp_interruption_data;
   15090             : 
   15091             : 
   15092           4 : class RegExpInterruptionThread : public v8::base::Thread {
   15093             :  public:
   15094             :   explicit RegExpInterruptionThread(v8::Isolate* isolate)
   15095           4 :       : Thread(Options("TimeoutThread")), isolate_(isolate) {}
   15096             : 
   15097           4 :   void Run() override {
   15098          32 :     for (v8::base::Relaxed_Store(&regexp_interruption_data.loop_count, 0);
   15099             :          v8::base::Relaxed_Load(&regexp_interruption_data.loop_count) < 7;
   15100             :          v8::base::Relaxed_AtomicIncrement(&regexp_interruption_data.loop_count,
   15101             :                                            1)) {
   15102             :       // Wait a bit before requesting GC.
   15103          28 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15104          28 :       reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
   15105             :     }
   15106             :     // Wait a bit before terminating.
   15107           4 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
   15108           4 :     isolate_->TerminateExecution();
   15109           4 :   }
   15110             : 
   15111             :  private:
   15112             :   v8::Isolate* isolate_;
   15113             : };
   15114             : 
   15115             : 
   15116           2 : void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
   15117             :                  v8::GCCallbackFlags flags) {
   15118           2 :   if (v8::base::Relaxed_Load(&regexp_interruption_data.loop_count) != 2) {
   15119           2 :     return;
   15120             :   }
   15121           0 :   v8::HandleScope scope(isolate);
   15122             :   v8::Local<v8::String> string = v8::Local<v8::String>::New(
   15123           0 :       CcTest::isolate(), regexp_interruption_data.string);
   15124           0 :   string->MakeExternal(regexp_interruption_data.string_resource);
   15125             : }
   15126             : 
   15127             : 
   15128             : // Test that RegExp execution can be interrupted.  Specifically, we test
   15129             : // * interrupting with GC
   15130             : // * turn the subject string from one-byte internal to two-byte external string
   15131             : // * force termination
   15132       25879 : TEST(RegExpInterruption) {
   15133           4 :   LocalContext env;
   15134           8 :   v8::HandleScope scope(env->GetIsolate());
   15135             : 
   15136           4 :   RegExpInterruptionThread timeout_thread(env->GetIsolate());
   15137             : 
   15138           4 :   env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
   15139             :   static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
   15140           4 :   i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
   15141           4 :   v8::Local<v8::String> string = v8_str(one_byte_content);
   15142             : 
   15143          20 :   env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
   15144           4 :   regexp_interruption_data.string.Reset(env->GetIsolate(), string);
   15145             :   regexp_interruption_data.string_resource = new UC16VectorResource(
   15146          12 :       i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
   15147             : 
   15148           8 :   v8::TryCatch try_catch(env->GetIsolate());
   15149           4 :   timeout_thread.Start();
   15150             : 
   15151             :   CompileRun("/((a*)*)*b/.exec(a)");
   15152           4 :   CHECK(try_catch.HasTerminated());
   15153             : 
   15154           4 :   timeout_thread.Join();
   15155             : 
   15156             :   regexp_interruption_data.string.Reset();
   15157           4 :   i::DeleteArray(uc16_content);
   15158           4 : }
   15159             : 
   15160             : // Test that we cannot set a property on the global object if there
   15161             : // is a read-only property in the prototype chain.
   15162       25880 : TEST(ReadOnlyPropertyInGlobalProto) {
   15163           5 :   v8::Isolate* isolate = CcTest::isolate();
   15164           5 :   v8::HandleScope scope(isolate);
   15165           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15166          10 :   LocalContext context(nullptr, templ);
   15167           5 :   v8::Local<v8::Object> global = context->Global();
   15168             :   v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
   15169          20 :       global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
   15170             :   global_proto->DefineOwnProperty(context.local(), v8_str("x"),
   15171          20 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15172          10 :       .FromJust();
   15173             :   global_proto->DefineOwnProperty(context.local(), v8_str("y"),
   15174          20 :                                   v8::Integer::New(isolate, 0), v8::ReadOnly)
   15175          10 :       .FromJust();
   15176             :   // Check without 'eval' or 'with'.
   15177             :   v8::Local<v8::Value> res =
   15178           5 :       CompileRun("function f() { x = 42; return x; }; f()");
   15179          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15180             :   // Check with 'eval'.
   15181           5 :   res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
   15182          15 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15183             :   // Check with 'with'.
   15184           5 :   res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
   15185          20 :   CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
   15186           5 : }
   15187             : 
   15188             : 
   15189       25880 : TEST(CreateDataProperty) {
   15190           5 :   LocalContext env;
   15191           5 :   v8::Isolate* isolate = env->GetIsolate();
   15192          10 :   v8::HandleScope handle_scope(isolate);
   15193             : 
   15194             :   CompileRun(
   15195             :       "var a = {};"
   15196             :       "var b = [];"
   15197             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15198             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15199             : 
   15200             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15201          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15202             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15203          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15204             :   {
   15205             :     // Can't change a non-configurable properties.
   15206           5 :     v8::TryCatch try_catch(isolate);
   15207          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
   15208             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15209           5 :     CHECK(!try_catch.HasCaught());
   15210          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
   15211             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15212           5 :     CHECK(!try_catch.HasCaught());
   15213             :     v8::Local<v8::Value> val =
   15214          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15215           5 :     CHECK(val->IsNumber());
   15216          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15217             :   }
   15218             : 
   15219             :   {
   15220             :     // Set a regular property.
   15221           5 :     v8::TryCatch try_catch(isolate);
   15222          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
   15223             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15224           5 :     CHECK(!try_catch.HasCaught());
   15225             :     v8::Local<v8::Value> val =
   15226          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15227           5 :     CHECK(val->IsNumber());
   15228          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15229             :   }
   15230             : 
   15231             :   {
   15232             :     // Set an indexed property.
   15233           5 :     v8::TryCatch try_catch(isolate);
   15234          20 :     CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
   15235             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15236           5 :     CHECK(!try_catch.HasCaught());
   15237           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15238           5 :     CHECK(val->IsNumber());
   15239          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15240             :   }
   15241             : 
   15242             :   {
   15243             :     // Special cases for arrays.
   15244           5 :     v8::TryCatch try_catch(isolate);
   15245          20 :     CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
   15246             :                                    v8::Integer::New(isolate, 1)).FromJust());
   15247           5 :     CHECK(!try_catch.HasCaught());
   15248             :   }
   15249             :   {
   15250             :     // Special cases for arrays: index exceeds the array's length
   15251           5 :     v8::TryCatch try_catch(isolate);
   15252          15 :     CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
   15253             :               .FromJust());
   15254           5 :     CHECK(!try_catch.HasCaught());
   15255           5 :     CHECK_EQ(2U, arr->Length());
   15256           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15257           5 :     CHECK(val->IsNumber());
   15258          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15259             : 
   15260             :     // Set an existing entry.
   15261          15 :     CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
   15262             :               .FromJust());
   15263           5 :     CHECK(!try_catch.HasCaught());
   15264           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15265           5 :     CHECK(val->IsNumber());
   15266          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15267             :   }
   15268             : 
   15269             :   CompileRun("Object.freeze(a);");
   15270             :   {
   15271             :     // Can't change non-extensible objects.
   15272           5 :     v8::TryCatch try_catch(isolate);
   15273          20 :     CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
   15274             :                                    v8::Integer::New(isolate, 42)).FromJust());
   15275           5 :     CHECK(!try_catch.HasCaught());
   15276             :   }
   15277             : 
   15278           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15279           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15280             :   v8::Local<v8::Object> access_checked =
   15281           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15282             :   {
   15283           5 :     v8::TryCatch try_catch(isolate);
   15284          20 :     CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
   15285             :                                              v8::Integer::New(isolate, 42))
   15286             :               .IsNothing());
   15287           5 :     CHECK(try_catch.HasCaught());
   15288           5 :   }
   15289           5 : }
   15290             : 
   15291             : 
   15292       25880 : TEST(DefineOwnProperty) {
   15293           5 :   LocalContext env;
   15294           5 :   v8::Isolate* isolate = env->GetIsolate();
   15295          10 :   v8::HandleScope handle_scope(isolate);
   15296             : 
   15297             :   CompileRun(
   15298             :       "var a = {};"
   15299             :       "var b = [];"
   15300             :       "Object.defineProperty(a, 'foo', {value: 23});"
   15301             :       "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
   15302             : 
   15303             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15304          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15305             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15306          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15307             :   {
   15308             :     // Can't change a non-configurable properties.
   15309           5 :     v8::TryCatch try_catch(isolate);
   15310          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
   15311             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15312           5 :     CHECK(!try_catch.HasCaught());
   15313          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
   15314             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15315           5 :     CHECK(!try_catch.HasCaught());
   15316             :     v8::Local<v8::Value> val =
   15317          15 :         obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
   15318           5 :     CHECK(val->IsNumber());
   15319          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15320             :   }
   15321             : 
   15322             :   {
   15323             :     // Set a regular property.
   15324           5 :     v8::TryCatch try_catch(isolate);
   15325          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
   15326             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15327           5 :     CHECK(!try_catch.HasCaught());
   15328             :     v8::Local<v8::Value> val =
   15329          15 :         obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
   15330           5 :     CHECK(val->IsNumber());
   15331          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15332             :   }
   15333             : 
   15334             :   {
   15335             :     // Set an indexed property.
   15336           5 :     v8::TryCatch try_catch(isolate);
   15337          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
   15338             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15339           5 :     CHECK(!try_catch.HasCaught());
   15340           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15341           5 :     CHECK(val->IsNumber());
   15342          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15343             :   }
   15344             : 
   15345             :   {
   15346             :     // Special cases for arrays.
   15347           5 :     v8::TryCatch try_catch(isolate);
   15348          20 :     CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
   15349             :                                   v8::Integer::New(isolate, 1)).FromJust());
   15350           5 :     CHECK(!try_catch.HasCaught());
   15351             :   }
   15352             :   {
   15353             :     // Special cases for arrays: index exceeds the array's length
   15354           5 :     v8::TryCatch try_catch(isolate);
   15355          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
   15356             :                                  v8::Integer::New(isolate, 23)).FromJust());
   15357           5 :     CHECK(!try_catch.HasCaught());
   15358           5 :     CHECK_EQ(2U, arr->Length());
   15359           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
   15360           5 :     CHECK(val->IsNumber());
   15361          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15362             : 
   15363             :     // Set an existing entry.
   15364          20 :     CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
   15365             :                                  v8::Integer::New(isolate, 42)).FromJust());
   15366           5 :     CHECK(!try_catch.HasCaught());
   15367           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15368           5 :     CHECK(val->IsNumber());
   15369          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15370             :   }
   15371             : 
   15372             :   {
   15373             :     // Set a non-writable property.
   15374           5 :     v8::TryCatch try_catch(isolate);
   15375          20 :     CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
   15376             :                                  v8::Integer::New(isolate, 42),
   15377             :                                  v8::ReadOnly).FromJust());
   15378           5 :     CHECK(!try_catch.HasCaught());
   15379             :     v8::Local<v8::Value> val =
   15380          15 :         obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
   15381           5 :     CHECK(val->IsNumber());
   15382          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15383          15 :     CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
   15384             :                                     env.local(), v8_str("lala")).FromJust());
   15385           5 :     CHECK(!try_catch.HasCaught());
   15386             :   }
   15387             : 
   15388             :   CompileRun("Object.freeze(a);");
   15389             :   {
   15390             :     // Can't change non-extensible objects.
   15391           5 :     v8::TryCatch try_catch(isolate);
   15392          20 :     CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
   15393             :                                   v8::Integer::New(isolate, 42)).FromJust());
   15394           5 :     CHECK(!try_catch.HasCaught());
   15395             :   }
   15396             : 
   15397           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15398           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15399             :   v8::Local<v8::Object> access_checked =
   15400           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15401             :   {
   15402           5 :     v8::TryCatch try_catch(isolate);
   15403          20 :     CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
   15404             :                                             v8::Integer::New(isolate, 42))
   15405             :               .IsNothing());
   15406           5 :     CHECK(try_catch.HasCaught());
   15407           5 :   }
   15408           5 : }
   15409             : 
   15410       25880 : TEST(DefineProperty) {
   15411           5 :   LocalContext env;
   15412           5 :   v8::Isolate* isolate = env->GetIsolate();
   15413          10 :   v8::HandleScope handle_scope(isolate);
   15414             : 
   15415             :   v8::Local<v8::Name> p;
   15416             : 
   15417             :   CompileRun(
   15418             :       "var a = {};"
   15419             :       "var b = [];"
   15420             :       "Object.defineProperty(a, 'v1', {value: 23});"
   15421             :       "Object.defineProperty(a, 'v2', {value: 23, configurable: true});");
   15422             : 
   15423             :   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
   15424          25 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   15425             :   v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
   15426          25 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   15427             : 
   15428          10 :   v8::PropertyDescriptor desc(v8_num(42));
   15429             :   {
   15430             :     // Use a data descriptor.
   15431             : 
   15432             :     // Cannot change a non-configurable property.
   15433           5 :     p = v8_str("v1");
   15434           5 :     v8::TryCatch try_catch(isolate);
   15435          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc).FromJust());
   15436           5 :     CHECK(!try_catch.HasCaught());
   15437          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15438           5 :     CHECK(val->IsNumber());
   15439          10 :     CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
   15440             : 
   15441             :     // Change a configurable property.
   15442           5 :     p = v8_str("v2");
   15443          10 :     obj->DefineProperty(env.local(), p, desc).FromJust();
   15444          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15445           5 :     CHECK(!try_catch.HasCaught());
   15446          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15447           5 :     CHECK(val->IsNumber());
   15448          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15449             : 
   15450             :     // Check that missing writable has default value false.
   15451           5 :     p = v8_str("v12");
   15452          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15453           5 :     CHECK(!try_catch.HasCaught());
   15454          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15455           5 :     CHECK(val->IsNumber());
   15456          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15457          10 :     v8::PropertyDescriptor desc2(v8_num(43));
   15458          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc2).FromJust());
   15459          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15460          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15461          10 :     CHECK(!try_catch.HasCaught());
   15462             :   }
   15463             : 
   15464             :   {
   15465             :     // Set a regular property.
   15466           5 :     p = v8_str("v3");
   15467           5 :     v8::TryCatch try_catch(isolate);
   15468          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15469           5 :     CHECK(!try_catch.HasCaught());
   15470          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15471           5 :     CHECK(val->IsNumber());
   15472          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15473             :   }
   15474             : 
   15475             :   {
   15476             :     // Set an indexed property.
   15477           5 :     v8::TryCatch try_catch(isolate);
   15478          15 :     CHECK(obj->DefineProperty(env.local(), v8_str("1"), desc).FromJust());
   15479           5 :     CHECK(!try_catch.HasCaught());
   15480           5 :     v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
   15481           5 :     CHECK(val->IsNumber());
   15482          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15483             :   }
   15484             : 
   15485             :   {
   15486             :     // No special case when changing array length.
   15487           5 :     v8::TryCatch try_catch(isolate);
   15488             :     // Use a writable descriptor, otherwise the next test, that changes
   15489             :     // the array length will fail.
   15490          10 :     v8::PropertyDescriptor desc(v8_num(42), true);
   15491          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("length"), desc).FromJust());
   15492          10 :     CHECK(!try_catch.HasCaught());
   15493             :   }
   15494             : 
   15495             :   {
   15496             :     // Special cases for arrays: index exceeds the array's length.
   15497           5 :     v8::TryCatch try_catch(isolate);
   15498          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("100"), desc).FromJust());
   15499           5 :     CHECK(!try_catch.HasCaught());
   15500           5 :     CHECK_EQ(101U, arr->Length());
   15501           5 :     v8::Local<v8::Value> val = arr->Get(env.local(), 100).ToLocalChecked();
   15502           5 :     CHECK(val->IsNumber());
   15503          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15504             : 
   15505             :     // Set an existing entry.
   15506          15 :     CHECK(arr->DefineProperty(env.local(), v8_str("0"), desc).FromJust());
   15507           5 :     CHECK(!try_catch.HasCaught());
   15508           5 :     val = arr->Get(env.local(), 0).ToLocalChecked();
   15509           5 :     CHECK(val->IsNumber());
   15510          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15511             :   }
   15512             : 
   15513             :   {
   15514             :     // Use a generic descriptor.
   15515           5 :     v8::PropertyDescriptor desc_generic;
   15516             : 
   15517           5 :     p = v8_str("v4");
   15518          10 :     v8::TryCatch try_catch(isolate);
   15519          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_generic).FromJust());
   15520           5 :     CHECK(!try_catch.HasCaught());
   15521          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15522           5 :     CHECK(val->IsUndefined());
   15523             : 
   15524          15 :     obj->Set(env.local(), p, v8_num(1)).FromJust();
   15525           5 :     CHECK(!try_catch.HasCaught());
   15526             : 
   15527          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15528           5 :     CHECK(val->IsUndefined());
   15529          10 :     CHECK(!try_catch.HasCaught());
   15530             :   }
   15531             : 
   15532             :   {
   15533             :     // Use a data descriptor with undefined value.
   15534           5 :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate));
   15535             : 
   15536          10 :     v8::TryCatch try_catch(isolate);
   15537          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15538           5 :     CHECK(!try_catch.HasCaught());
   15539          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15540           5 :     CHECK(val->IsUndefined());
   15541          10 :     CHECK(!try_catch.HasCaught());
   15542             :   }
   15543             : 
   15544             :   {
   15545             :     // Use a descriptor with attribute == v8::ReadOnly.
   15546           5 :     v8::PropertyDescriptor desc_read_only(v8_num(42), false);
   15547           5 :     desc_read_only.set_enumerable(true);
   15548           5 :     desc_read_only.set_configurable(true);
   15549             : 
   15550           5 :     p = v8_str("v5");
   15551          10 :     v8::TryCatch try_catch(isolate);
   15552          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_read_only).FromJust());
   15553           5 :     CHECK(!try_catch.HasCaught());
   15554          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15555           5 :     CHECK(val->IsNumber());
   15556          10 :     CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
   15557          10 :     CHECK_EQ(v8::ReadOnly,
   15558             :              obj->GetPropertyAttributes(env.local(), p).FromJust());
   15559          10 :     CHECK(!try_catch.HasCaught());
   15560             :   }
   15561             : 
   15562             :   {
   15563             :     // Use an accessor descriptor with empty handles.
   15564             :     v8::PropertyDescriptor desc_empty(v8::Undefined(isolate),
   15565           5 :                                       v8::Undefined(isolate));
   15566             : 
   15567           5 :     p = v8_str("v6");
   15568          10 :     v8::TryCatch try_catch(isolate);
   15569          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15570           5 :     CHECK(!try_catch.HasCaught());
   15571          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15572           5 :     CHECK(val->IsUndefined());
   15573          10 :     CHECK(!try_catch.HasCaught());
   15574             :   }
   15575             : 
   15576             :   {
   15577             :     // Use an accessor descriptor.
   15578             :     CompileRun(
   15579             :         "var set = function(x) {this.val = 2*x;};"
   15580             :         "var get = function() {return this.val || 0;};");
   15581             : 
   15582             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   15583          25 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   15584             :     v8::Local<v8::Function> set = v8::Local<v8::Function>::Cast(
   15585          25 :         env->Global()->Get(env.local(), v8_str("set")).ToLocalChecked());
   15586           5 :     v8::PropertyDescriptor desc(get, set);
   15587             : 
   15588           5 :     p = v8_str("v7");
   15589          10 :     v8::TryCatch try_catch(isolate);
   15590          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15591           5 :     CHECK(!try_catch.HasCaught());
   15592             : 
   15593          10 :     v8::Local<v8::Value> val = obj->Get(env.local(), p).ToLocalChecked();
   15594           5 :     CHECK(val->IsNumber());
   15595          10 :     CHECK_EQ(0.0, val->NumberValue(env.local()).FromJust());
   15596           5 :     CHECK(!try_catch.HasCaught());
   15597             : 
   15598          15 :     obj->Set(env.local(), p, v8_num(7)).FromJust();
   15599           5 :     CHECK(!try_catch.HasCaught());
   15600             : 
   15601          10 :     val = obj->Get(env.local(), p).ToLocalChecked();
   15602           5 :     CHECK(val->IsNumber());
   15603          10 :     CHECK_EQ(14.0, val->NumberValue(env.local()).FromJust());
   15604          10 :     CHECK(!try_catch.HasCaught());
   15605             :   }
   15606             : 
   15607             :   {
   15608             :     // Redefine an existing property.
   15609             : 
   15610             :     // desc = {value: 42, enumerable: true}
   15611           5 :     v8::PropertyDescriptor desc(v8_num(42));
   15612           5 :     desc.set_enumerable(true);
   15613             : 
   15614           5 :     p = v8_str("v8");
   15615          10 :     v8::TryCatch try_catch(isolate);
   15616          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15617           5 :     CHECK(!try_catch.HasCaught());
   15618             : 
   15619             :     // desc = {enumerable: true}
   15620          10 :     v8::PropertyDescriptor desc_true((v8::Local<v8::Value>()));
   15621           5 :     desc_true.set_enumerable(true);
   15622             : 
   15623             :     // Successful redefinition because all present attributes have the same
   15624             :     // value as the current descriptor.
   15625          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_true).FromJust());
   15626           5 :     CHECK(!try_catch.HasCaught());
   15627             : 
   15628             :     // desc = {}
   15629          10 :     v8::PropertyDescriptor desc_empty;
   15630             :     // Successful redefinition because no attributes are overwritten in the
   15631             :     // current descriptor.
   15632          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15633           5 :     CHECK(!try_catch.HasCaught());
   15634             : 
   15635             :     // desc = {enumerable: false}
   15636          10 :     v8::PropertyDescriptor desc_false((v8::Local<v8::Value>()));
   15637           5 :     desc_false.set_enumerable(false);
   15638             :     // Not successful because we cannot define a different value for enumerable.
   15639          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_false).FromJust());
   15640          10 :     CHECK(!try_catch.HasCaught());
   15641             :   }
   15642             : 
   15643             :   {
   15644             :     // Redefine a property that has a getter.
   15645             :     CompileRun("var get = function() {};");
   15646             :     v8::Local<v8::Function> get = v8::Local<v8::Function>::Cast(
   15647          25 :         env->Global()->Get(env.local(), v8_str("get")).ToLocalChecked());
   15648             : 
   15649             :     // desc = {get: function() {}}
   15650           5 :     v8::PropertyDescriptor desc(get, v8::Local<v8::Function>());
   15651          10 :     v8::TryCatch try_catch(isolate);
   15652             : 
   15653           5 :     p = v8_str("v9");
   15654          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15655           5 :     CHECK(!try_catch.HasCaught());
   15656             : 
   15657             :     // desc_empty = {}
   15658             :     // Successful because we are not redefining the current getter.
   15659          10 :     v8::PropertyDescriptor desc_empty;
   15660          10 :     CHECK(obj->DefineProperty(env.local(), p, desc_empty).FromJust());
   15661           5 :     CHECK(!try_catch.HasCaught());
   15662             : 
   15663             :     // desc = {get: function() {}}
   15664             :     // Successful because we redefine the getter with its current value.
   15665          10 :     CHECK(obj->DefineProperty(env.local(), p, desc).FromJust());
   15666           5 :     CHECK(!try_catch.HasCaught());
   15667             : 
   15668             :     // desc = {get: undefined}
   15669             :     v8::PropertyDescriptor desc_undefined(v8::Undefined(isolate),
   15670          10 :                                           v8::Local<v8::Function>());
   15671             :     // Not successful because we cannot redefine with the current value of get
   15672             :     // with undefined.
   15673          10 :     CHECK(!obj->DefineProperty(env.local(), p, desc_undefined).FromJust());
   15674          10 :     CHECK(!try_catch.HasCaught());
   15675             :   }
   15676             : 
   15677             :   CompileRun("Object.freeze(a);");
   15678             :   {
   15679             :     // We cannot change non-extensible objects.
   15680           5 :     v8::TryCatch try_catch(isolate);
   15681          15 :     CHECK(!obj->DefineProperty(env.local(), v8_str("v10"), desc).FromJust());
   15682           5 :     CHECK(!try_catch.HasCaught());
   15683             :   }
   15684             : 
   15685           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   15686           5 :   templ->SetAccessCheckCallback(AccessAlwaysBlocked);
   15687             :   v8::Local<v8::Object> access_checked =
   15688           5 :       templ->NewInstance(env.local()).ToLocalChecked();
   15689             :   {
   15690           5 :     v8::TryCatch try_catch(isolate);
   15691          15 :     CHECK(access_checked->DefineProperty(env.local(), v8_str("v11"), desc)
   15692             :               .IsNothing());
   15693           5 :     CHECK(try_catch.HasCaught());
   15694           5 :   }
   15695           5 : }
   15696             : 
   15697       25881 : THREADED_TEST(GetCurrentContextWhenNotInContext) {
   15698             :   i::Isolate* isolate = CcTest::i_isolate();
   15699           6 :   CHECK_NOT_NULL(isolate);
   15700           6 :   CHECK(isolate->context().is_null());
   15701             :   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   15702           6 :   v8::HandleScope scope(v8_isolate);
   15703             :   // The following should not crash, but return an empty handle.
   15704           6 :   v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
   15705           6 :   CHECK(current.IsEmpty());
   15706           6 : }
   15707             : 
   15708             : 
   15709             : // Check that a variable declaration with no explicit initialization
   15710             : // value does shadow an existing property in the prototype chain.
   15711       25881 : THREADED_TEST(InitGlobalVarInProtoChain) {
   15712           6 :   LocalContext context;
   15713          12 :   v8::HandleScope scope(context->GetIsolate());
   15714             :   // Introduce a variable in the prototype chain.
   15715             :   CompileRun("__proto__.x = 42");
   15716             :   v8::Local<v8::Value> result = CompileRun("var x = 43; x");
   15717           6 :   CHECK(!result->IsUndefined());
   15718          18 :   CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
   15719           6 : }
   15720             : 
   15721             : 
   15722             : // Regression test for issue 398.
   15723             : // If a function is added to an object, creating a constant function
   15724             : // field, and the result is cloned, replacing the constant function on the
   15725             : // original should not affect the clone.
   15726             : // See http://code.google.com/p/v8/issues/detail?id=398
   15727       25881 : THREADED_TEST(ReplaceConstantFunction) {
   15728           6 :   LocalContext context;
   15729           6 :   v8::Isolate* isolate = context->GetIsolate();
   15730          12 :   v8::HandleScope scope(isolate);
   15731           6 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   15732             :   v8::Local<v8::FunctionTemplate> func_templ =
   15733           6 :       v8::FunctionTemplate::New(isolate);
   15734           6 :   v8::Local<v8::String> foo_string = v8_str("foo");
   15735             :   obj->Set(context.local(), foo_string,
   15736          24 :            func_templ->GetFunction(context.local()).ToLocalChecked())
   15737          12 :       .FromJust();
   15738           6 :   v8::Local<v8::Object> obj_clone = obj->Clone();
   15739          24 :   obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
   15740          18 :   CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
   15741           6 : }
   15742             : 
   15743             : 
   15744         504 : static void CheckElementValue(i::Isolate* isolate,
   15745             :                               int expected,
   15746             :                               i::Handle<i::Object> obj,
   15747             :                               int offset) {
   15748             :   i::Object element =
   15749        1008 :       *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
   15750         504 :   CHECK_EQ(expected, i::Smi::ToInt(element));
   15751         504 : }
   15752             : 
   15753             : 
   15754             : template <class ExternalArrayClass, class ElementType>
   15755         162 : static void ObjectWithExternalArrayTestHelper(Local<Context> context,
   15756             :                                               v8::Local<Object> obj,
   15757             :                                               int element_count,
   15758             :                                               i::ExternalArrayType array_type,
   15759             :                                               int64_t low, int64_t high) {
   15760             :   i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
   15761         162 :   v8::Isolate* v8_isolate = context->GetIsolate();
   15762             :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
   15763         486 :   obj->Set(context, v8_str("field"), v8::Int32::New(v8_isolate, 1503))
   15764         324 :       .FromJust();
   15765         648 :   CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
   15766             :   v8::Local<v8::Value> result = CompileRun("ext_array.field");
   15767         324 :   CHECK_EQ(1503, result->Int32Value(context).FromJust());
   15768             :   result = CompileRun("ext_array[1]");
   15769         324 :   CHECK_EQ(1, result->Int32Value(context).FromJust());
   15770             : 
   15771             :   // Check assigned smis
   15772             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15773             :                       "  ext_array[i] = i;"
   15774             :                       "}"
   15775             :                       "var sum = 0;"
   15776             :                       "for (var i = 0; i < 8; i++) {"
   15777             :                       "  sum += ext_array[i];"
   15778             :                       "}"
   15779             :                       "sum;");
   15780             : 
   15781         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15782             :   // Check pass through of assigned smis
   15783             :   result = CompileRun("var sum = 0;"
   15784             :                       "for (var i = 0; i < 8; i++) {"
   15785             :                       "  sum += ext_array[i] = ext_array[i] = -i;"
   15786             :                       "}"
   15787             :                       "sum;");
   15788         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   15789             : 
   15790             : 
   15791             :   // Check assigned smis in reverse order
   15792             :   result = CompileRun("for (var i = 8; --i >= 0; ) {"
   15793             :                       "  ext_array[i] = i;"
   15794             :                       "}"
   15795             :                       "var sum = 0;"
   15796             :                       "for (var i = 0; i < 8; i++) {"
   15797             :                       "  sum += ext_array[i];"
   15798             :                       "}"
   15799             :                       "sum;");
   15800         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15801             : 
   15802             :   // Check pass through of assigned HeapNumbers
   15803             :   result = CompileRun("var sum = 0;"
   15804             :                       "for (var i = 0; i < 16; i+=2) {"
   15805             :                       "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
   15806             :                       "}"
   15807             :                       "sum;");
   15808         324 :   CHECK_EQ(-28, result->Int32Value(context).FromJust());
   15809             : 
   15810             :   // Check assigned HeapNumbers
   15811             :   result = CompileRun("for (var i = 0; i < 16; i+=2) {"
   15812             :                       "  ext_array[i] = (i * 0.5);"
   15813             :                       "}"
   15814             :                       "var sum = 0;"
   15815             :                       "for (var i = 0; i < 16; i+=2) {"
   15816             :                       "  sum += ext_array[i];"
   15817             :                       "}"
   15818             :                       "sum;");
   15819         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15820             : 
   15821             :   // Check assigned HeapNumbers in reverse order
   15822             :   result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
   15823             :                       "  ext_array[i] = (i * 0.5);"
   15824             :                       "}"
   15825             :                       "var sum = 0;"
   15826             :                       "for (var i = 0; i < 16; i+=2) {"
   15827             :                       "  sum += ext_array[i];"
   15828             :                       "}"
   15829             :                       "sum;");
   15830         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15831             : 
   15832             :   i::ScopedVector<char> test_buf(1024);
   15833             : 
   15834             :   // Check legal boundary conditions.
   15835             :   // The repeated loads and stores ensure the ICs are exercised.
   15836             :   const char* boundary_program =
   15837             :       "var res = 0;"
   15838             :       "for (var i = 0; i < 16; i++) {"
   15839             :       "  ext_array[i] = %lld;"
   15840             :       "  if (i > 8) {"
   15841             :       "    res = ext_array[i];"
   15842             :       "  }"
   15843             :       "}"
   15844             :       "res;";
   15845         162 :   i::SNPrintF(test_buf,
   15846             :               boundary_program,
   15847             :               low);
   15848             :   result = CompileRun(test_buf.start());
   15849         324 :   CHECK_EQ(low, result->IntegerValue(context).FromJust());
   15850             : 
   15851         162 :   i::SNPrintF(test_buf,
   15852             :               boundary_program,
   15853             :               high);
   15854             :   result = CompileRun(test_buf.start());
   15855         324 :   CHECK_EQ(high, result->IntegerValue(context).FromJust());
   15856             : 
   15857             :   // Check misprediction of type in IC.
   15858             :   result = CompileRun("var tmp_array = ext_array;"
   15859             :                       "var sum = 0;"
   15860             :                       "for (var i = 0; i < 8; i++) {"
   15861             :                       "  tmp_array[i] = i;"
   15862             :                       "  sum += tmp_array[i];"
   15863             :                       "  if (i == 4) {"
   15864             :                       "    tmp_array = {};"
   15865             :                       "  }"
   15866             :                       "}"
   15867             :                       "sum;");
   15868             :   // Force GC to trigger verification.
   15869         162 :   CcTest::CollectAllGarbage();
   15870         324 :   CHECK_EQ(28, result->Int32Value(context).FromJust());
   15871             : 
   15872             :   // Make sure out-of-range loads do not throw.
   15873         162 :   i::SNPrintF(test_buf,
   15874             :               "var caught_exception = false;"
   15875             :               "try {"
   15876             :               "  ext_array[%d];"
   15877             :               "} catch (e) {"
   15878             :               "  caught_exception = true;"
   15879             :               "}"
   15880             :               "caught_exception;",
   15881             :               element_count);
   15882             :   result = CompileRun(test_buf.start());
   15883         162 :   CHECK(!result->BooleanValue(v8_isolate));
   15884             : 
   15885             :   // Make sure out-of-range stores do not throw.
   15886         162 :   i::SNPrintF(test_buf,
   15887             :               "var caught_exception = false;"
   15888             :               "try {"
   15889             :               "  ext_array[%d] = 1;"
   15890             :               "} catch (e) {"
   15891             :               "  caught_exception = true;"
   15892             :               "}"
   15893             :               "caught_exception;",
   15894             :               element_count);
   15895             :   result = CompileRun(test_buf.start());
   15896         162 :   CHECK(!result->BooleanValue(v8_isolate));
   15897             : 
   15898             :   // Check other boundary conditions, values and operations.
   15899             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15900             :                       "  ext_array[7] = undefined;"
   15901             :                       "}"
   15902             :                       "ext_array[7];");
   15903         324 :   CHECK_EQ(0, result->Int32Value(context).FromJust());
   15904         162 :   if (array_type == i::kExternalFloat64Array ||
   15905             :       array_type == i::kExternalFloat32Array) {
   15906          72 :     CHECK(std::isnan(
   15907             :         i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
   15908             :   } else {
   15909         126 :     CheckElementValue(isolate, 0, jsobj, 7);
   15910             :   }
   15911             : 
   15912             :   result = CompileRun("for (var i = 0; i < 8; i++) {"
   15913             :                       "  ext_array[6] = '2.3';"
   15914             :                       "}"
   15915             :                       "ext_array[6];");
   15916         324 :   CHECK_EQ(2, result->Int32Value(context).FromJust());
   15917         324 :   CHECK_EQ(2,
   15918             :            static_cast<int>(
   15919             :                i::Object::GetElement(
   15920             :                    isolate, jsobj, 6).ToHandleChecked()->Number()));
   15921             : 
   15922         162 :   if (array_type != i::kExternalFloat32Array &&
   15923             :       array_type != i::kExternalFloat64Array) {
   15924             :     // Though the specification doesn't state it, be explicit about
   15925             :     // converting NaNs and +/-Infinity to zero.
   15926             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15927             :                         "  ext_array[i] = 5;"
   15928             :                         "}"
   15929             :                         "for (var i = 0; i < 8; i++) {"
   15930             :                         "  ext_array[i] = NaN;"
   15931             :                         "}"
   15932             :                         "ext_array[5];");
   15933         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   15934         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   15935             : 
   15936             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15937             :                         "  ext_array[i] = 5;"
   15938             :                         "}"
   15939             :                         "for (var i = 0; i < 8; i++) {"
   15940             :                         "  ext_array[i] = Infinity;"
   15941             :                         "}"
   15942             :                         "ext_array[5];");
   15943             :     int expected_value =
   15944         126 :         (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
   15945         252 :     CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
   15946         126 :     CheckElementValue(isolate, expected_value, jsobj, 5);
   15947             : 
   15948             :     result = CompileRun("for (var i = 0; i < 8; i++) {"
   15949             :                         "  ext_array[i] = 5;"
   15950             :                         "}"
   15951             :                         "for (var i = 0; i < 8; i++) {"
   15952             :                         "  ext_array[i] = -Infinity;"
   15953             :                         "}"
   15954             :                         "ext_array[5];");
   15955         252 :     CHECK_EQ(0, result->Int32Value(context).FromJust());
   15956         126 :     CheckElementValue(isolate, 0, jsobj, 5);
   15957             : 
   15958             :     // Check truncation behavior of integral arrays.
   15959             :     const char* unsigned_data =
   15960             :         "var source_data = [0.6, 10.6];"
   15961             :         "var expected_results = [0, 10];";
   15962             :     const char* signed_data =
   15963             :         "var source_data = [0.6, 10.6, -0.6, -10.6];"
   15964             :         "var expected_results = [0, 10, 0, -10];";
   15965             :     const char* pixel_data =
   15966             :         "var source_data = [0.6, 10.6];"
   15967             :         "var expected_results = [1, 11];";
   15968             :     bool is_unsigned = (array_type == i::kExternalUint8Array ||
   15969             :                         array_type == i::kExternalUint16Array ||
   15970         126 :                         array_type == i::kExternalUint32Array);
   15971             :     bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
   15972             : 
   15973         126 :     i::SNPrintF(test_buf,
   15974             :                 "%s"
   15975             :                 "var all_passed = true;"
   15976             :                 "for (var i = 0; i < source_data.length; i++) {"
   15977             :                 "  for (var j = 0; j < 8; j++) {"
   15978             :                 "    ext_array[j] = source_data[i];"
   15979             :                 "  }"
   15980             :                 "  all_passed = all_passed &&"
   15981             :                 "               (ext_array[5] == expected_results[i]);"
   15982             :                 "}"
   15983             :                 "all_passed;",
   15984             :                 (is_unsigned ?
   15985             :                      unsigned_data :
   15986         126 :                      (is_pixel_data ? pixel_data : signed_data)));
   15987             :     result = CompileRun(test_buf.start());
   15988         126 :     CHECK(result->BooleanValue(v8_isolate));
   15989             :   }
   15990             : 
   15991             :   i::Handle<ExternalArrayClass> array(
   15992         486 :       ExternalArrayClass::cast(i::Handle<i::JSObject>::cast(jsobj)->elements()),
   15993         324 :       isolate);
   15994       19602 :   for (int i = 0; i < element_count; i++) {
   15995       36720 :     array->set(i, static_cast<ElementType>(i));
   15996             :   }
   15997             : 
   15998         162 :   bool old_natives_flag_sentry = i::FLAG_allow_natives_syntax;
   15999         162 :   i::FLAG_allow_natives_syntax = true;
   16000             : 
   16001             :   // Test complex assignments
   16002             :   result = CompileRun(
   16003             :       "function ee_op_test_complex_func(sum) {"
   16004             :       " for (var i = 0; i < 40; ++i) {"
   16005             :       "   sum += (ext_array[i] += 1);"
   16006             :       "   sum += (ext_array[i] -= 1);"
   16007             :       " } "
   16008             :       " return sum;"
   16009             :       "}"
   16010             :       "sum=0;"
   16011             :       "sum=ee_op_test_complex_func(sum);"
   16012             :       "sum=ee_op_test_complex_func(sum);"
   16013             :       "%OptimizeFunctionOnNextCall(ee_op_test_complex_func);"
   16014             :       "sum=ee_op_test_complex_func(sum);"
   16015             :       "sum;");
   16016         324 :   CHECK_EQ(4800, result->Int32Value(context).FromJust());
   16017             : 
   16018             :   // Test count operations
   16019             :   result = CompileRun(
   16020             :       "function ee_op_test_count_func(sum) {"
   16021             :       " for (var i = 0; i < 40; ++i) {"
   16022             :       "   sum += (++ext_array[i]);"
   16023             :       "   sum += (--ext_array[i]);"
   16024             :       " } "
   16025             :       " return sum;"
   16026             :       "}"
   16027             :       "sum=0;"
   16028             :       "sum=ee_op_test_count_func(sum);"
   16029             :       "sum=ee_op_test_count_func(sum);"
   16030             :       "%OptimizeFunctionOnNextCall(ee_op_test_count_func);"
   16031             :       "sum=ee_op_test_count_func(sum);"
   16032             :       "sum;");
   16033         324 :   CHECK_EQ(4800, result->Int32Value(context).FromJust());
   16034             : 
   16035         162 :   i::FLAG_allow_natives_syntax = old_natives_flag_sentry;
   16036             : 
   16037             :   result = CompileRun("ext_array[3] = 33;"
   16038             :                       "delete ext_array[3];"
   16039             :                       "ext_array[3];");
   16040         324 :   CHECK_EQ(33, result->Int32Value(context).FromJust());
   16041             : 
   16042             :   result = CompileRun(
   16043             :       "ext_array[0] = 10; ext_array[1] = 11;"
   16044             :       "ext_array[2] = 12; ext_array[3] = 13;"
   16045             :       "try { ext_array.__defineGetter__('2', function() { return 120; }); }"
   16046             :       "catch (e) { }"
   16047             :       "ext_array[2];");
   16048         324 :   CHECK_EQ(12, result->Int32Value(context).FromJust());
   16049             : 
   16050             :   result = CompileRun("var js_array = new Array(40);"
   16051             :                       "js_array[0] = 77;"
   16052             :                       "js_array;");
   16053         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16054             :                    ->Get(context, v8_str("0"))
   16055             :                    .ToLocalChecked()
   16056             :                    ->Int32Value(context)
   16057             :                    .FromJust());
   16058             : 
   16059             :   result = CompileRun("ext_array[1] = 23;"
   16060             :                       "ext_array.__proto__ = [];"
   16061             :                       "js_array.__proto__ = ext_array;"
   16062             :                       "js_array.concat(ext_array);");
   16063         648 :   CHECK_EQ(77, v8::Object::Cast(*result)
   16064             :                    ->Get(context, v8_str("0"))
   16065             :                    .ToLocalChecked()
   16066             :                    ->Int32Value(context)
   16067             :                    .FromJust());
   16068         648 :   CHECK_EQ(23, v8::Object::Cast(*result)
   16069             :                    ->Get(context, v8_str("1"))
   16070             :                    .ToLocalChecked()
   16071             :                    ->Int32Value(context)
   16072             :                    .FromJust());
   16073             : 
   16074             :   result = CompileRun("ext_array[1] = 23;");
   16075         324 :   CHECK_EQ(23, result->Int32Value(context).FromJust());
   16076         162 : }
   16077             : 
   16078             : 
   16079             : template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
   16080             :           class ElementType>
   16081          54 : static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
   16082             :                                       ElementType low, ElementType high) {
   16083          54 :   i::FLAG_allow_natives_syntax = true;
   16084          54 :   LocalContext context;
   16085             :   i::Isolate* isolate = CcTest::i_isolate();
   16086             :   i::Factory* factory = isolate->factory();
   16087         108 :   v8::HandleScope scope(context->GetIsolate());
   16088             :   const int kElementCount = 260;
   16089             :   i::Handle<i::JSTypedArray> jsobj =
   16090          54 :       factory->NewJSTypedArray(elements_kind, kElementCount);
   16091             :   i::Handle<FixedTypedArrayClass> fixed_array(
   16092         108 :       FixedTypedArrayClass::cast(jsobj->elements()), isolate);
   16093          54 :   CHECK_EQ(FixedTypedArrayClass::kInstanceType,
   16094             :            fixed_array->map()->instance_type());
   16095          54 :   CHECK_EQ(kElementCount, fixed_array->length());
   16096          54 :   CcTest::CollectAllGarbage();
   16097       14094 :   for (int i = 0; i < kElementCount; i++) {
   16098       26520 :     fixed_array->set(i, static_cast<ElementType>(i));
   16099             :   }
   16100             :   // Force GC to trigger verification.
   16101          54 :   CcTest::CollectAllGarbage();
   16102       14094 :   for (int i = 0; i < kElementCount; i++) {
   16103       14040 :     CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
   16104             :              static_cast<int64_t>(fixed_array->get_scalar(i)));
   16105             :   }
   16106             :   v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
   16107             : 
   16108          54 :   ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
   16109             :       context.local(), obj, kElementCount, array_type,
   16110             :       static_cast<int64_t>(low),
   16111         108 :       static_cast<int64_t>(high));
   16112          54 : }
   16113             : 
   16114             : 
   16115       25881 : THREADED_TEST(FixedUint8Array) {
   16116             :   FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
   16117           6 :       i::kExternalUint8Array, 0x0, 0xFF);
   16118           6 : }
   16119             : 
   16120             : 
   16121       25881 : THREADED_TEST(FixedUint8ClampedArray) {
   16122             :   FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
   16123             :                             i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
   16124           6 :       i::kExternalUint8ClampedArray, 0x0, 0xFF);
   16125           6 : }
   16126             : 
   16127             : 
   16128       25881 : THREADED_TEST(FixedInt8Array) {
   16129             :   FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
   16130           6 :       i::kExternalInt8Array, -0x80, 0x7F);
   16131           6 : }
   16132             : 
   16133             : 
   16134       25881 : THREADED_TEST(FixedUint16Array) {
   16135             :   FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
   16136           6 :       i::kExternalUint16Array, 0x0, 0xFFFF);
   16137           6 : }
   16138             : 
   16139             : 
   16140       25881 : THREADED_TEST(FixedInt16Array) {
   16141             :   FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
   16142           6 :       i::kExternalInt16Array, -0x8000, 0x7FFF);
   16143           6 : }
   16144             : 
   16145             : 
   16146       25881 : THREADED_TEST(FixedUint32Array) {
   16147             :   FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
   16148           6 :       i::kExternalUint32Array, 0x0, UINT_MAX);
   16149           6 : }
   16150             : 
   16151             : 
   16152       25881 : THREADED_TEST(FixedInt32Array) {
   16153             :   FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
   16154           6 :       i::kExternalInt32Array, INT_MIN, INT_MAX);
   16155           6 : }
   16156             : 
   16157             : 
   16158       25881 : THREADED_TEST(FixedFloat32Array) {
   16159             :   FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
   16160           6 :       i::kExternalFloat32Array, -500, 500);
   16161           6 : }
   16162             : 
   16163             : 
   16164       25881 : THREADED_TEST(FixedFloat64Array) {
   16165             :   FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
   16166           6 :       i::kExternalFloat64Array, -500, 500);
   16167           6 : }
   16168             : 
   16169             : 
   16170             : template <typename ElementType, typename TypedArray, class ExternalArrayClass,
   16171             :           class ArrayBufferType>
   16172         108 : void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
   16173             :                           int64_t high) {
   16174             :   const int kElementCount = 50;
   16175             : 
   16176             :   i::ScopedVector<ElementType> backing_store(kElementCount+2);
   16177             : 
   16178         216 :   LocalContext env;
   16179         108 :   v8::Isolate* isolate = env->GetIsolate();
   16180         216 :   v8::HandleScope handle_scope(isolate);
   16181             : 
   16182             :   Local<ArrayBufferType> ab =
   16183             :       ArrayBufferType::New(isolate, backing_store.start(),
   16184         108 :                            (kElementCount + 2) * sizeof(ElementType));
   16185             :   Local<TypedArray> ta =
   16186         108 :       TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
   16187         108 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
   16188         108 :   CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
   16189         108 :   CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
   16190         108 :   CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
   16191         432 :   CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
   16192             : 
   16193         108 :   ElementType* data = backing_store.start() + 2;
   16194        5508 :   for (int i = 0; i < kElementCount; i++) {
   16195        5400 :     data[i] = static_cast<ElementType>(i);
   16196             :   }
   16197             : 
   16198         108 :   ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
   16199         216 :       env.local(), ta, kElementCount, array_type, low, high);
   16200         108 : }
   16201             : 
   16202             : 
   16203       25881 : THREADED_TEST(Uint8Array) {
   16204             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16205           6 :                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16206           6 : }
   16207             : 
   16208             : 
   16209       25881 : THREADED_TEST(Int8Array) {
   16210             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16211           6 :                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
   16212           6 : }
   16213             : 
   16214             : 
   16215       25881 : THREADED_TEST(Uint16Array) {
   16216             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16217           6 :                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
   16218           6 : }
   16219             : 
   16220             : 
   16221       25881 : THREADED_TEST(Int16Array) {
   16222             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16223             :                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16224           6 :                                         0x7FFF);
   16225           6 : }
   16226             : 
   16227             : 
   16228       25881 : THREADED_TEST(Uint32Array) {
   16229             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16230           6 :                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
   16231           6 : }
   16232             : 
   16233             : 
   16234       25881 : THREADED_TEST(Int32Array) {
   16235             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16236             :                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16237           6 :                                         INT_MAX);
   16238           6 : }
   16239             : 
   16240             : 
   16241       25881 : THREADED_TEST(Float32Array) {
   16242             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16243           6 :                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
   16244           6 : }
   16245             : 
   16246             : 
   16247       25881 : THREADED_TEST(Float64Array) {
   16248             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16249           6 :                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
   16250           6 : }
   16251             : 
   16252             : 
   16253       25881 : THREADED_TEST(Uint8ClampedArray) {
   16254             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16255             :                        i::FixedUint8ClampedArray, v8::ArrayBuffer>(
   16256           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16257           6 : }
   16258             : 
   16259             : 
   16260       25881 : THREADED_TEST(DataView) {
   16261             :   const int kSize = 50;
   16262             : 
   16263             :   i::ScopedVector<uint8_t> backing_store(kSize+2);
   16264             : 
   16265          12 :   LocalContext env;
   16266           6 :   v8::Isolate* isolate = env->GetIsolate();
   16267          12 :   v8::HandleScope handle_scope(isolate);
   16268             : 
   16269             :   Local<v8::ArrayBuffer> ab =
   16270           6 :       v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16271           6 :   Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
   16272           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16273           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16274           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16275          24 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16276           6 : }
   16277             : 
   16278             : 
   16279       25881 : THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
   16280           6 :   LocalContext env;
   16281           6 :   v8::Isolate* isolate = env->GetIsolate();
   16282          12 :   v8::HandleScope handle_scope(isolate);
   16283             : 
   16284             :   // Make sure the pointer looks like a heap object
   16285             :   uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
   16286             : 
   16287             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16288           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16289             : 
   16290             :   // Should not crash
   16291           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16292           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16293           6 :   CcTest::CollectAllGarbage();
   16294           6 :   CcTest::CollectAllGarbage();
   16295             : 
   16296             :   // Should not move the pointer
   16297          12 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16298           6 : }
   16299             : 
   16300             : 
   16301       25881 : THREADED_TEST(SkipArrayBufferDuringScavenge) {
   16302           6 :   LocalContext env;
   16303           6 :   v8::Isolate* isolate = env->GetIsolate();
   16304          12 :   v8::HandleScope handle_scope(isolate);
   16305             : 
   16306             :   // Make sure the pointer looks like a heap object
   16307           6 :   Local<v8::Object> tmp = v8::Object::New(isolate);
   16308             :   uint8_t* store_ptr =
   16309           6 :       reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
   16310             : 
   16311             :   // Make `store_ptr` point to from space
   16312           6 :   CcTest::CollectGarbage(i::NEW_SPACE);
   16313             : 
   16314             :   // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
   16315           6 :   Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
   16316             : 
   16317             :   // Should not crash,
   16318             :   // i.e. backing store pointer should not be treated as a heap object pointer
   16319           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in survivor space now
   16320           6 :   CcTest::CollectGarbage(i::NEW_SPACE);  // in old gen now
   16321             : 
   16322             :   // Use `ab` to silence compiler warning
   16323          12 :   CHECK_EQ(ab->GetContents().Data(), store_ptr);
   16324           6 : }
   16325             : 
   16326             : 
   16327       25881 : THREADED_TEST(SharedUint8Array) {
   16328           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16329             :   TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
   16330           6 :                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
   16331           6 : }
   16332             : 
   16333             : 
   16334       25881 : THREADED_TEST(SharedInt8Array) {
   16335           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16336             :   TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
   16337             :                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
   16338           6 :                                               0x7F);
   16339           6 : }
   16340             : 
   16341             : 
   16342       25881 : THREADED_TEST(SharedUint16Array) {
   16343           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16344             :   TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
   16345             :                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
   16346           6 :                                               0xFFFF);
   16347           6 : }
   16348             : 
   16349             : 
   16350       25881 : THREADED_TEST(SharedInt16Array) {
   16351           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16352             :   TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
   16353             :                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
   16354           6 :                                               0x7FFF);
   16355           6 : }
   16356             : 
   16357             : 
   16358       25881 : THREADED_TEST(SharedUint32Array) {
   16359           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16360             :   TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
   16361             :                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
   16362           6 :                                               UINT_MAX);
   16363           6 : }
   16364             : 
   16365             : 
   16366       25881 : THREADED_TEST(SharedInt32Array) {
   16367           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16368             :   TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
   16369             :                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
   16370           6 :                                               INT_MAX);
   16371           6 : }
   16372             : 
   16373             : 
   16374       25881 : THREADED_TEST(SharedFloat32Array) {
   16375           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16376             :   TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
   16377             :                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
   16378           6 :                                               500);
   16379           6 : }
   16380             : 
   16381             : 
   16382       25881 : THREADED_TEST(SharedFloat64Array) {
   16383           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16384             :   TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
   16385             :                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
   16386           6 :                                               500);
   16387           6 : }
   16388             : 
   16389             : 
   16390       25881 : THREADED_TEST(SharedUint8ClampedArray) {
   16391           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16392             :   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
   16393             :                        i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
   16394           6 :       i::kExternalUint8ClampedArray, 0, 0xFF);
   16395           6 : }
   16396             : 
   16397             : 
   16398       25881 : THREADED_TEST(SharedDataView) {
   16399           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   16400             :   const int kSize = 50;
   16401             : 
   16402             :   i::ScopedVector<uint8_t> backing_store(kSize + 2);
   16403             : 
   16404          12 :   LocalContext env;
   16405           6 :   v8::Isolate* isolate = env->GetIsolate();
   16406          12 :   v8::HandleScope handle_scope(isolate);
   16407             : 
   16408             :   Local<v8::SharedArrayBuffer> ab =
   16409           6 :       v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
   16410             :   Local<v8::DataView> dv =
   16411           6 :       v8::DataView::New(ab, 2, kSize);
   16412           6 :   CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
   16413           6 :   CHECK_EQ(2u, dv->ByteOffset());
   16414           6 :   CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
   16415          24 :   CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
   16416           6 : }
   16417             : 
   16418             : #define IS_ARRAY_BUFFER_VIEW_TEST(View)                                     \
   16419             :   THREADED_TEST(Is##View) {                                                 \
   16420             :     LocalContext env;                                                       \
   16421             :     v8::Isolate* isolate = env->GetIsolate();                               \
   16422             :     v8::HandleScope handle_scope(isolate);                                  \
   16423             :                                                                             \
   16424             :     Local<Value> result = CompileRun(                                       \
   16425             :         "var ab = new ArrayBuffer(128);"                                    \
   16426             :         "new " #View "(ab)");                                               \
   16427             :     CHECK(result->IsArrayBufferView());                                     \
   16428             :     CHECK(result->Is##View());                                              \
   16429             :     CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
   16430             :   }
   16431             : 
   16432       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
   16433       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
   16434       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
   16435       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
   16436       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
   16437       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
   16438       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
   16439       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
   16440       25905 : IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
   16441       25905 : IS_ARRAY_BUFFER_VIEW_TEST(DataView)
   16442             : 
   16443             : #undef IS_ARRAY_BUFFER_VIEW_TEST
   16444             : 
   16445             : 
   16446             : 
   16447       25881 : THREADED_TEST(ScriptContextDependence) {
   16448           6 :   LocalContext c1;
   16449          12 :   v8::HandleScope scope(c1->GetIsolate());
   16450             :   const char *source = "foo";
   16451             :   v8::Local<v8::Script> dep = v8_compile(source);
   16452             :   v8::ScriptCompiler::Source script_source(
   16453             :       v8::String::NewFromUtf8(c1->GetIsolate(), source,
   16454           6 :                               v8::NewStringType::kNormal)
   16455           6 :           .ToLocalChecked());
   16456             :   v8::Local<v8::UnboundScript> indep =
   16457           6 :       v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
   16458           6 :           .ToLocalChecked();
   16459             :   c1->Global()
   16460             :       ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
   16461           6 :                                                 v8::NewStringType::kNormal)
   16462             :                             .ToLocalChecked(),
   16463          30 :             v8::Integer::New(c1->GetIsolate(), 100))
   16464          12 :       .FromJust();
   16465          18 :   CHECK_EQ(
   16466             :       dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
   16467             :       100);
   16468          24 :   CHECK_EQ(indep->BindToCurrentContext()
   16469             :                ->Run(c1.local())
   16470             :                .ToLocalChecked()
   16471             :                ->Int32Value(c1.local())
   16472             :                .FromJust(),
   16473             :            100);
   16474          12 :   LocalContext c2;
   16475             :   c2->Global()
   16476             :       ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
   16477           6 :                                                 v8::NewStringType::kNormal)
   16478             :                             .ToLocalChecked(),
   16479          30 :             v8::Integer::New(c2->GetIsolate(), 101))
   16480          12 :       .FromJust();
   16481          18 :   CHECK_EQ(
   16482             :       dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
   16483             :       100);
   16484          24 :   CHECK_EQ(indep->BindToCurrentContext()
   16485             :                ->Run(c2.local())
   16486             :                .ToLocalChecked()
   16487             :                ->Int32Value(c2.local())
   16488             :                .FromJust(),
   16489           6 :            101);
   16490           6 : }
   16491             : 
   16492             : 
   16493       25881 : THREADED_TEST(StackTrace) {
   16494           6 :   LocalContext context;
   16495          12 :   v8::HandleScope scope(context->GetIsolate());
   16496          12 :   v8::TryCatch try_catch(context->GetIsolate());
   16497             :   const char *source = "function foo() { FAIL.FAIL; }; foo();";
   16498           6 :   v8::Local<v8::String> src = v8_str(source);
   16499           6 :   v8::Local<v8::String> origin = v8_str("stack-trace-test");
   16500             :   v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
   16501          30 :   CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
   16502             :                                                  &script_source)
   16503             :             .ToLocalChecked()
   16504             :             ->BindToCurrentContext()
   16505             :             ->Run(context.local())
   16506             :             .IsEmpty());
   16507           6 :   CHECK(try_catch.HasCaught());
   16508             :   v8::String::Utf8Value stack(
   16509             :       context->GetIsolate(),
   16510          18 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   16511          18 :   CHECK_NOT_NULL(strstr(*stack, "at foo (stack-trace-test"));
   16512           6 : }
   16513             : 
   16514             : 
   16515             : // Checks that a StackFrame has certain expected values.
   16516         100 : void checkStackFrame(const char* expected_script_name,
   16517             :                      const char* expected_func_name, int expected_line_number,
   16518             :                      int expected_column, bool is_eval, bool is_constructor,
   16519             :                      v8::Local<v8::StackFrame> frame) {
   16520         100 :   v8::HandleScope scope(CcTest::isolate());
   16521         300 :   v8::String::Utf8Value func_name(CcTest::isolate(), frame->GetFunctionName());
   16522         300 :   v8::String::Utf8Value script_name(CcTest::isolate(), frame->GetScriptName());
   16523         100 :   if (*script_name == nullptr) {
   16524             :     // The situation where there is no associated script, like for evals.
   16525          35 :     CHECK_NULL(expected_script_name);
   16526             :   } else {
   16527          65 :     CHECK_NOT_NULL(strstr(*script_name, expected_script_name));
   16528             :   }
   16529         200 :   CHECK_NOT_NULL(strstr(*func_name, expected_func_name));
   16530         100 :   CHECK_EQ(expected_line_number, frame->GetLineNumber());
   16531         100 :   CHECK_EQ(expected_column, frame->GetColumn());
   16532         100 :   CHECK_EQ(is_eval, frame->IsEval());
   16533         200 :   CHECK_EQ(is_constructor, frame->IsConstructor());
   16534         100 : }
   16535             : 
   16536             : 
   16537         180 : void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
   16538          35 :   v8::HandleScope scope(args.GetIsolate());
   16539             :   const char* origin = "capture-stack-trace-test";
   16540             :   const int kOverviewTest = 1;
   16541             :   const int kDetailedTest = 2;
   16542             :   const int kFunctionName = 3;
   16543             :   const int kDisplayName = 4;
   16544             :   const int kFunctionNameAndDisplayName = 5;
   16545             :   const int kDisplayNameIsNotString = 6;
   16546             :   const int kFunctionNameIsNotString = 7;
   16547             : 
   16548          35 :   CHECK_EQ(args.Length(), 1);
   16549             : 
   16550          35 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   16551             :   v8::Isolate* isolate = args.GetIsolate();
   16552          70 :   int testGroup = args[0]->Int32Value(context).FromJust();
   16553          35 :   if (testGroup == kOverviewTest) {
   16554             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16555           5 :         args.GetIsolate(), 10, v8::StackTrace::kOverview);
   16556           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   16557             :     checkStackFrame(origin, "bar", 2, 10, false, false,
   16558           5 :                     stackTrace->GetFrame(args.GetIsolate(), 0));
   16559             :     checkStackFrame(origin, "foo", 6, 3, false, true,
   16560           5 :                     stackTrace->GetFrame(isolate, 1));
   16561             :     // This is the source string inside the eval which has the call to foo.
   16562             :     checkStackFrame(nullptr, "", 1, 1, true, false,
   16563           5 :                     stackTrace->GetFrame(isolate, 2));
   16564             :     // The last frame is an anonymous function which has the initial eval call.
   16565             :     checkStackFrame(origin, "", 8, 7, false, false,
   16566           5 :                     stackTrace->GetFrame(isolate, 3));
   16567          30 :   } else if (testGroup == kDetailedTest) {
   16568             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16569           5 :         args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   16570           5 :     CHECK_EQ(4, stackTrace->GetFrameCount());
   16571             :     checkStackFrame(origin, "bat", 4, 22, false, false,
   16572           5 :                     stackTrace->GetFrame(isolate, 0));
   16573             :     checkStackFrame(origin, "baz", 8, 3, false, true,
   16574           5 :                     stackTrace->GetFrame(isolate, 1));
   16575             :     bool is_eval = true;
   16576             :     // This is the source string inside the eval which has the call to baz.
   16577             :     checkStackFrame(nullptr, "", 1, 1, is_eval, false,
   16578           5 :                     stackTrace->GetFrame(isolate, 2));
   16579             :     // The last frame is an anonymous function which has the initial eval call.
   16580             :     checkStackFrame(origin, "", 10, 1, false, false,
   16581           5 :                     stackTrace->GetFrame(isolate, 3));
   16582          25 :   } else if (testGroup == kFunctionName) {
   16583             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16584           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16585           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16586             :     checkStackFrame(nullptr, "function.name", 3, 1, true, false,
   16587           5 :                     stackTrace->GetFrame(isolate, 0));
   16588          20 :   } else if (testGroup == kDisplayName) {
   16589             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16590           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16591           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16592             :     checkStackFrame(nullptr, "function.displayName", 3, 1, true, false,
   16593           5 :                     stackTrace->GetFrame(isolate, 0));
   16594          15 :   } else if (testGroup == kFunctionNameAndDisplayName) {
   16595             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16596           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16597           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16598             :     checkStackFrame(nullptr, "function.displayName", 3, 1, true, false,
   16599           5 :                     stackTrace->GetFrame(isolate, 0));
   16600          10 :   } else if (testGroup == kDisplayNameIsNotString) {
   16601             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16602           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16603           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16604             :     checkStackFrame(nullptr, "function.name", 3, 1, true, false,
   16605           5 :                     stackTrace->GetFrame(isolate, 0));
   16606           5 :   } else if (testGroup == kFunctionNameIsNotString) {
   16607             :     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   16608           5 :         args.GetIsolate(), 5, v8::StackTrace::kOverview);
   16609           5 :     CHECK_EQ(3, stackTrace->GetFrameCount());
   16610             :     checkStackFrame(nullptr, "", 3, 1, true, false,
   16611           5 :                     stackTrace->GetFrame(isolate, 0));
   16612          35 :   }
   16613          35 : }
   16614             : 
   16615             : 
   16616             : // Tests the C++ StackTrace API.
   16617             : // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
   16618             : // THREADED_TEST(CaptureStackTrace) {
   16619       25880 : TEST(CaptureStackTrace) {
   16620           5 :   v8::Isolate* isolate = CcTest::isolate();
   16621           5 :   v8::HandleScope scope(isolate);
   16622           5 :   v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
   16623           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   16624             :   templ->Set(v8_str("AnalyzeStackInNativeCode"),
   16625          15 :              v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
   16626          10 :   LocalContext context(nullptr, templ);
   16627             : 
   16628             :   // Test getting OVERVIEW information. Should ignore information that is not
   16629             :   // script name, function name, line number, and column offset.
   16630             :   const char *overview_source =
   16631             :     "function bar() {\n"
   16632             :     "  var y; AnalyzeStackInNativeCode(1);\n"
   16633             :     "}\n"
   16634             :     "function foo() {\n"
   16635             :     "\n"
   16636             :     "  bar();\n"
   16637             :     "}\n"
   16638             :     "var x;eval('new foo();');";
   16639           5 :   v8::Local<v8::String> overview_src = v8_str(overview_source);
   16640             :   v8::ScriptCompiler::Source script_source(overview_src,
   16641             :                                            v8::ScriptOrigin(origin));
   16642             :   v8::Local<Value> overview_result(
   16643             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
   16644           5 :           .ToLocalChecked()
   16645             :           ->BindToCurrentContext()
   16646          15 :           ->Run(context.local())
   16647           5 :           .ToLocalChecked());
   16648           5 :   CHECK(!overview_result.IsEmpty());
   16649           5 :   CHECK(overview_result->IsObject());
   16650             : 
   16651             :   // Test getting DETAILED information.
   16652             :   const char *detailed_source =
   16653             :     "function bat() {AnalyzeStackInNativeCode(2);\n"
   16654             :     "}\n"
   16655             :     "\n"
   16656             :     "function baz() {\n"
   16657             :     "  bat();\n"
   16658             :     "}\n"
   16659             :     "eval('new baz();');";
   16660           5 :   v8::Local<v8::String> detailed_src = v8_str(detailed_source);
   16661             :   // Make the script using a non-zero line and column offset.
   16662           5 :   v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
   16663           5 :   v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
   16664             :   v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
   16665             :   v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
   16666             :   v8::Local<v8::UnboundScript> detailed_script(
   16667             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
   16668           5 :           .ToLocalChecked());
   16669             :   v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
   16670          10 :                                        ->Run(context.local())
   16671           5 :                                        .ToLocalChecked());
   16672           5 :   CHECK(!detailed_result.IsEmpty());
   16673           5 :   CHECK(detailed_result->IsObject());
   16674             : 
   16675             :   // Test using function.name and function.displayName in stack trace
   16676             :   const char* function_name_source =
   16677             :       "function bar(function_name, display_name, testGroup) {\n"
   16678             :       "  var f = new Function(`AnalyzeStackInNativeCode(${testGroup});`);\n"
   16679             :       "  if (function_name) {\n"
   16680             :       "    Object.defineProperty(f, 'name', { value: function_name });\n"
   16681             :       "  }\n"
   16682             :       "  if (display_name) {\n"
   16683             :       "    f.displayName = display_name;"
   16684             :       "  }\n"
   16685             :       "  f()\n"
   16686             :       "}\n"
   16687             :       "bar('function.name', undefined, 3);\n"
   16688             :       "bar(undefined, 'function.displayName', 4);\n"
   16689             :       "bar('function.name', 'function.displayName', 5);\n"
   16690             :       "bar('function.name', 239, 6);\n"
   16691             :       "bar(239, undefined, 7);\n";
   16692             :   v8::Local<v8::String> function_name_src =
   16693             :       v8::String::NewFromUtf8(isolate, function_name_source,
   16694             :                               v8::NewStringType::kNormal)
   16695           5 :           .ToLocalChecked();
   16696             :   v8::ScriptCompiler::Source script_source3(function_name_src,
   16697             :                                             v8::ScriptOrigin(origin));
   16698             :   v8::Local<Value> function_name_result(
   16699             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
   16700           5 :           .ToLocalChecked()
   16701             :           ->BindToCurrentContext()
   16702          15 :           ->Run(context.local())
   16703           5 :           .ToLocalChecked());
   16704          10 :   CHECK(!function_name_result.IsEmpty());
   16705           5 : }
   16706             : 
   16707             : 
   16708           5 : static void StackTraceForUncaughtExceptionListener(
   16709             :     v8::Local<v8::Message> message, v8::Local<Value>) {
   16710           5 :   report_count++;
   16711           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16712           5 :   CHECK_EQ(2, stack_trace->GetFrameCount());
   16713             :   checkStackFrame("origin", "foo", 2, 3, false, false,
   16714           5 :                   stack_trace->GetFrame(message->GetIsolate(), 0));
   16715             :   checkStackFrame("origin", "bar", 5, 3, false, false,
   16716           5 :                   stack_trace->GetFrame(message->GetIsolate(), 1));
   16717           5 : }
   16718             : 
   16719             : 
   16720       25880 : TEST(CaptureStackTraceForUncaughtException) {
   16721           5 :   report_count = 0;
   16722           5 :   LocalContext env;
   16723           5 :   v8::Isolate* isolate = env->GetIsolate();
   16724          10 :   v8::HandleScope scope(isolate);
   16725           5 :   isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
   16726           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16727             : 
   16728             :   CompileRunWithOrigin(
   16729             :       "function foo() {\n"
   16730             :       "  throw 1;\n"
   16731             :       "};\n"
   16732             :       "function bar() {\n"
   16733             :       "  foo();\n"
   16734             :       "};",
   16735             :       "origin");
   16736           5 :   v8::Local<v8::Object> global = env->Global();
   16737             :   Local<Value> trouble =
   16738          20 :       global->Get(env.local(), v8_str("bar")).ToLocalChecked();
   16739           5 :   CHECK(trouble->IsFunction());
   16740          10 :   CHECK(Function::Cast(*trouble)
   16741             :             ->Call(env.local(), global, 0, nullptr)
   16742             :             .IsEmpty());
   16743           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16744           5 :   isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
   16745          10 :   CHECK_EQ(1, report_count);
   16746           5 : }
   16747             : 
   16748       25880 : TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
   16749           5 :   LocalContext env;
   16750           5 :   v8::Isolate* isolate = env->GetIsolate();
   16751          10 :   v8::HandleScope scope(isolate);
   16752             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
   16753           5 :                                                      v8::StackTrace::kDetailed);
   16754             : 
   16755             :   CompileRun(
   16756             :       "var setters = ['column', 'lineNumber', 'scriptName',\n"
   16757             :       "    'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
   16758             :       "    'isConstructor'];\n"
   16759             :       "for (var i = 0; i < setters.length; i++) {\n"
   16760             :       "  var prop = setters[i];\n"
   16761             :       "  Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
   16762             :       "}\n");
   16763             :   CompileRun("throw 'exception';");
   16764          10 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16765           5 : }
   16766             : 
   16767             : static int asm_warning_triggered = 0;
   16768             : 
   16769           5 : static void AsmJsWarningListener(v8::Local<v8::Message> message,
   16770             :                                  v8::Local<Value>) {
   16771             :   DCHECK_EQ(v8::Isolate::kMessageWarning, message->ErrorLevel());
   16772           5 :   asm_warning_triggered = 1;
   16773           5 : }
   16774             : 
   16775       25880 : TEST(AsmJsWarning) {
   16776           5 :   i::FLAG_validate_asm = true;
   16777           5 :   if (i::FLAG_suppress_asm_messages) return;
   16778             : 
   16779           5 :   LocalContext env;
   16780           5 :   v8::Isolate* isolate = env->GetIsolate();
   16781          10 :   v8::HandleScope scope(isolate);
   16782             : 
   16783           5 :   asm_warning_triggered = 0;
   16784             :   isolate->AddMessageListenerWithErrorLevel(AsmJsWarningListener,
   16785           5 :                                             v8::Isolate::kMessageAll);
   16786             :   CompileRun(
   16787             :       "function module() {\n"
   16788             :       "  'use asm';\n"
   16789             :       "  var x = 'hi';\n"
   16790             :       "  return {};\n"
   16791             :       "}\n"
   16792             :       "module();");
   16793             :   DCHECK_EQ(1, asm_warning_triggered);
   16794          10 :   isolate->RemoveMessageListeners(AsmJsWarningListener);
   16795             : }
   16796             : 
   16797             : static int error_level_message_count = 0;
   16798             : static int expected_error_level = 0;
   16799             : 
   16800          20 : static void ErrorLevelListener(v8::Local<v8::Message> message,
   16801             :                                v8::Local<Value>) {
   16802             :   DCHECK_EQ(expected_error_level, message->ErrorLevel());
   16803          20 :   ++error_level_message_count;
   16804          20 : }
   16805             : 
   16806       25880 : TEST(ErrorLevelWarning) {
   16807           5 :   LocalContext env;
   16808           5 :   v8::Isolate* isolate = env->GetIsolate();
   16809             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   16810          10 :   v8::HandleScope scope(isolate);
   16811             : 
   16812             :   const char* source = "fake = 1;";
   16813           5 :   v8::Local<v8::Script> lscript = CompileWithOrigin(source, "test");
   16814             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   16815          10 :       v8::Utils::OpenHandle(*lscript->GetUnboundScript()));
   16816          10 :   CHECK(obj->script()->IsScript());
   16817          10 :   i::Handle<i::Script> script(i::Script::cast(obj->script()), i_isolate);
   16818             : 
   16819             :   int levels[] = {
   16820             :       v8::Isolate::kMessageLog, v8::Isolate::kMessageInfo,
   16821             :       v8::Isolate::kMessageDebug, v8::Isolate::kMessageWarning,
   16822           5 :   };
   16823           5 :   error_level_message_count = 0;
   16824             :   isolate->AddMessageListenerWithErrorLevel(ErrorLevelListener,
   16825           5 :                                             v8::Isolate::kMessageAll);
   16826          25 :   for (size_t i = 0; i < arraysize(levels); i++) {
   16827          20 :     i::MessageLocation location(script, 0, 0);
   16828             :     i::Handle<i::String> msg(i_isolate->factory()->InternalizeOneByteString(
   16829          20 :         i::StaticCharVector("test")));
   16830             :     i::Handle<i::JSMessageObject> message =
   16831             :         i::MessageHandler::MakeMessageObject(
   16832             :             i_isolate, i::MessageTemplate::kAsmJsInvalid, &location, msg,
   16833          20 :             i::Handle<i::FixedArray>::null());
   16834          20 :     message->set_error_level(levels[i]);
   16835          20 :     expected_error_level = levels[i];
   16836          20 :     i::MessageHandler::ReportMessage(i_isolate, &location, message);
   16837             :   }
   16838           5 :   isolate->RemoveMessageListeners(ErrorLevelListener);
   16839           5 :   DCHECK_EQ(arraysize(levels), error_level_message_count);
   16840           5 : }
   16841             : 
   16842           5 : static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
   16843             :                                            v8::Local<Value>) {
   16844           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16845           5 :   v8::Isolate* isolate = message->GetIsolate();
   16846           5 :   CHECK_EQ(5, stack_trace->GetFrameCount());
   16847             :   checkStackFrame("origin", "foo:0", 4, 7, false, false,
   16848           5 :                   stack_trace->GetFrame(isolate, 0));
   16849             :   checkStackFrame("origin", "foo:1", 5, 27, false, false,
   16850           5 :                   stack_trace->GetFrame(isolate, 1));
   16851             :   checkStackFrame("origin", "foo", 5, 27, false, false,
   16852           5 :                   stack_trace->GetFrame(isolate, 2));
   16853             :   checkStackFrame("origin", "foo", 5, 27, false, false,
   16854           5 :                   stack_trace->GetFrame(isolate, 3));
   16855             :   checkStackFrame("origin", "", 1, 14, false, false,
   16856           5 :                   stack_trace->GetFrame(isolate, 4));
   16857           5 : }
   16858             : 
   16859             : 
   16860       25880 : TEST(GetStackTraceContainsFunctionsWithFunctionName) {
   16861           5 :   LocalContext env;
   16862           5 :   v8::Isolate* isolate = env->GetIsolate();
   16863          10 :   v8::HandleScope scope(isolate);
   16864             : 
   16865             :   CompileRunWithOrigin(
   16866             :       "function gen(name, counter) {\n"
   16867             :       "  var f = function foo() {\n"
   16868             :       "    if (counter === 0)\n"
   16869             :       "      throw 1;\n"
   16870             :       "    gen(name, counter - 1)();\n"
   16871             :       "  };\n"
   16872             :       "  if (counter == 3) {\n"
   16873             :       "    Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
   16874             :       "  } else {\n"
   16875             :       "    Object.defineProperty(f, 'name', {writable:true});\n"
   16876             :       "    if (counter == 2)\n"
   16877             :       "      f.name = 42;\n"
   16878             :       "    else\n"
   16879             :       "      f.name = name + ':' + counter;\n"
   16880             :       "  }\n"
   16881             :       "  return f;\n"
   16882             :       "};",
   16883             :       "origin");
   16884             : 
   16885           5 :   isolate->AddMessageListener(StackTraceFunctionNameListener);
   16886           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16887             :   CompileRunWithOrigin("gen('foo', 3)();", "origin");
   16888           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16889          10 :   isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
   16890           5 : }
   16891             : 
   16892             : 
   16893           5 : static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
   16894             :                                      v8::Local<v8::Value> data) {
   16895             :   // Use the frame where JavaScript is called from.
   16896           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16897           5 :   CHECK(!stack_trace.IsEmpty());
   16898           5 :   int frame_count = stack_trace->GetFrameCount();
   16899           5 :   CHECK_EQ(3, frame_count);
   16900           5 :   int line_number[] = {1, 2, 5};
   16901          20 :   for (int i = 0; i < frame_count; i++) {
   16902          30 :     CHECK_EQ(line_number[i],
   16903             :              stack_trace->GetFrame(message->GetIsolate(), i)->GetLineNumber());
   16904             :   }
   16905           5 : }
   16906             : 
   16907             : 
   16908             : // Test that we only return the stack trace at the site where the exception
   16909             : // is first thrown (not where it is rethrown).
   16910       25880 : TEST(RethrowStackTrace) {
   16911           5 :   LocalContext env;
   16912           5 :   v8::Isolate* isolate = env->GetIsolate();
   16913          10 :   v8::HandleScope scope(isolate);
   16914             :   // We make sure that
   16915             :   // - the stack trace of the ReferenceError in g() is reported.
   16916             :   // - the stack trace is not overwritten when e1 is rethrown by t().
   16917             :   // - the stack trace of e2 does not overwrite that of e1.
   16918             :   const char* source =
   16919             :       "function g() { error; }          \n"
   16920             :       "function f() { g(); }            \n"
   16921             :       "function t(e) { throw e; }       \n"
   16922             :       "try {                            \n"
   16923             :       "  f();                           \n"
   16924             :       "} catch (e1) {                   \n"
   16925             :       "  try {                          \n"
   16926             :       "    error;                       \n"
   16927             :       "  } catch (e2) {                 \n"
   16928             :       "    t(e1);                       \n"
   16929             :       "  }                              \n"
   16930             :       "}                                \n";
   16931           5 :   isolate->AddMessageListener(RethrowStackTraceHandler);
   16932           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16933             :   CompileRun(source);
   16934           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16935          10 :   isolate->RemoveMessageListeners(RethrowStackTraceHandler);
   16936           5 : }
   16937             : 
   16938             : 
   16939           5 : static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
   16940             :                                               v8::Local<v8::Value> data) {
   16941           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16942           5 :   CHECK(!stack_trace.IsEmpty());
   16943           5 :   int frame_count = stack_trace->GetFrameCount();
   16944           5 :   CHECK_EQ(2, frame_count);
   16945           5 :   int line_number[] = {3, 7};
   16946          15 :   for (int i = 0; i < frame_count; i++) {
   16947          20 :     CHECK_EQ(line_number[i],
   16948             :              stack_trace->GetFrame(message->GetIsolate(), i)->GetLineNumber());
   16949             :   }
   16950           5 : }
   16951             : 
   16952             : 
   16953             : // Test that we do not recognize identity for primitive exceptions.
   16954       25880 : TEST(RethrowPrimitiveStackTrace) {
   16955           5 :   LocalContext env;
   16956           5 :   v8::Isolate* isolate = env->GetIsolate();
   16957          10 :   v8::HandleScope scope(isolate);
   16958             :   // We do not capture stack trace for non Error objects on creation time.
   16959             :   // Instead, we capture the stack trace on last throw.
   16960             :   const char* source =
   16961             :       "function g() { throw 404; }      \n"
   16962             :       "function f() { g(); }            \n"
   16963             :       "function t(e) { throw e; }       \n"
   16964             :       "try {                            \n"
   16965             :       "  f();                           \n"
   16966             :       "} catch (e1) {                   \n"
   16967             :       "  t(e1)                          \n"
   16968             :       "}                                \n";
   16969           5 :   isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
   16970           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16971             :   CompileRun(source);
   16972           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   16973          10 :   isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
   16974           5 : }
   16975             : 
   16976             : 
   16977           5 : static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
   16978             :                                              v8::Local<v8::Value> data) {
   16979             :   // Use the frame where JavaScript is called from.
   16980           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   16981           5 :   CHECK(!stack_trace.IsEmpty());
   16982           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   16983          10 :   CHECK_EQ(1, stack_trace->GetFrame(message->GetIsolate(), 0)->GetLineNumber());
   16984           5 : }
   16985             : 
   16986             : 
   16987             : // Test that the stack trace is captured when the error object is created and
   16988             : // not where it is thrown.
   16989       25880 : TEST(RethrowExistingStackTrace) {
   16990           5 :   LocalContext env;
   16991           5 :   v8::Isolate* isolate = env->GetIsolate();
   16992          10 :   v8::HandleScope scope(isolate);
   16993             :   const char* source =
   16994             :       "var e = new Error();           \n"
   16995             :       "throw e;                       \n";
   16996           5 :   isolate->AddMessageListener(RethrowExistingStackTraceHandler);
   16997           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   16998             :   CompileRun(source);
   16999           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17000          10 :   isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
   17001           5 : }
   17002             : 
   17003             : 
   17004           5 : static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
   17005             :                                                v8::Local<v8::Value> data) {
   17006             :   // Use the frame where JavaScript is called from.
   17007           5 :   v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17008           5 :   CHECK(!stack_trace.IsEmpty());
   17009           5 :   CHECK_EQ(1, stack_trace->GetFrameCount());
   17010          10 :   CHECK_EQ(2, stack_trace->GetFrame(message->GetIsolate(), 0)->GetLineNumber());
   17011           5 : }
   17012             : 
   17013             : 
   17014             : // Test that the stack trace is captured where the bogus Error object is thrown.
   17015       25880 : TEST(RethrowBogusErrorStackTrace) {
   17016           5 :   LocalContext env;
   17017           5 :   v8::Isolate* isolate = env->GetIsolate();
   17018          10 :   v8::HandleScope scope(isolate);
   17019             :   const char* source =
   17020             :       "var e = {__proto__: new Error()} \n"
   17021             :       "throw e;                         \n";
   17022           5 :   isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
   17023           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(true);
   17024             :   CompileRun(source);
   17025           5 :   isolate->SetCaptureStackTraceForUncaughtExceptions(false);
   17026          10 :   isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
   17027           5 : }
   17028             : 
   17029             : 
   17030             : v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
   17031             : int promise_reject_counter = 0;
   17032             : int promise_revoke_counter = 0;
   17033             : int promise_reject_after_resolved_counter = 0;
   17034             : int promise_resolve_after_resolved_counter = 0;
   17035             : int promise_reject_msg_line_number = -1;
   17036             : int promise_reject_msg_column_number = -1;
   17037             : int promise_reject_line_number = -1;
   17038             : int promise_reject_column_number = -1;
   17039             : int promise_reject_frame_count = -1;
   17040             : bool promise_reject_is_shared_cross_origin = false;
   17041             : 
   17042         140 : void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
   17043         140 :   v8::Local<v8::Object> global = CcTest::global();
   17044         140 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17045         140 :   CHECK_NE(v8::Promise::PromiseState::kPending,
   17046             :            reject_message.GetPromise()->State());
   17047         140 :   switch (reject_message.GetEvent()) {
   17048             :     case v8::kPromiseRejectWithNoHandler: {
   17049          95 :       promise_reject_counter++;
   17050         190 :       global->Set(context, v8_str("rejected"), reject_message.GetPromise())
   17051         190 :           .FromJust();
   17052         190 :       global->Set(context, v8_str("value"), reject_message.GetValue())
   17053         190 :           .FromJust();
   17054             :       v8::Local<v8::Message> message = v8::Exception::CreateMessage(
   17055          95 :           CcTest::isolate(), reject_message.GetValue());
   17056          95 :       v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
   17057             : 
   17058             :       promise_reject_msg_line_number =
   17059         190 :           message->GetLineNumber(context).FromJust();
   17060             :       promise_reject_msg_column_number =
   17061         190 :           message->GetStartColumn(context).FromJust() + 1;
   17062             :       promise_reject_is_shared_cross_origin =
   17063          95 :           message->IsSharedCrossOrigin();
   17064             : 
   17065          95 :       if (!stack_trace.IsEmpty()) {
   17066          35 :         promise_reject_frame_count = stack_trace->GetFrameCount();
   17067          35 :         if (promise_reject_frame_count > 0) {
   17068         150 :           CHECK(stack_trace->GetFrame(CcTest::isolate(), 0)
   17069             :                     ->GetScriptName()
   17070             :                     ->Equals(context, v8_str("pro"))
   17071             :                     .FromJust());
   17072             :           promise_reject_line_number =
   17073          60 :               stack_trace->GetFrame(CcTest::isolate(), 0)->GetLineNumber();
   17074             :           promise_reject_column_number =
   17075          60 :               stack_trace->GetFrame(CcTest::isolate(), 0)->GetColumn();
   17076             :         } else {
   17077           5 :           promise_reject_line_number = -1;
   17078           5 :           promise_reject_column_number = -1;
   17079             :         }
   17080             :       }
   17081             :       break;
   17082             :     }
   17083             :     case v8::kPromiseHandlerAddedAfterReject: {
   17084          30 :       promise_revoke_counter++;
   17085          60 :       global->Set(context, v8_str("revoked"), reject_message.GetPromise())
   17086          60 :           .FromJust();
   17087          30 :       CHECK(reject_message.GetValue().IsEmpty());
   17088             :       break;
   17089             :     }
   17090             :     case v8::kPromiseRejectAfterResolved: {
   17091          10 :       promise_reject_after_resolved_counter++;
   17092          10 :       break;
   17093             :     }
   17094             :     case v8::kPromiseResolveAfterResolved: {
   17095           5 :       promise_resolve_after_resolved_counter++;
   17096           5 :       break;
   17097             :     }
   17098             :   }
   17099         140 : }
   17100             : 
   17101             : 
   17102         600 : v8::Local<v8::Promise> GetPromise(const char* name) {
   17103             :   return v8::Local<v8::Promise>::Cast(
   17104             :       CcTest::global()
   17105        1800 :           ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
   17106        1200 :           .ToLocalChecked());
   17107             : }
   17108             : 
   17109             : 
   17110          35 : v8::Local<v8::Value> RejectValue() {
   17111             :   return CcTest::global()
   17112         105 :       ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17113          70 :       .ToLocalChecked();
   17114             : }
   17115             : 
   17116             : 
   17117          70 : void ResetPromiseStates() {
   17118          70 :   promise_reject_counter = 0;
   17119          70 :   promise_revoke_counter = 0;
   17120          70 :   promise_reject_after_resolved_counter = 0;
   17121          70 :   promise_resolve_after_resolved_counter = 0;
   17122          70 :   promise_reject_msg_line_number = -1;
   17123          70 :   promise_reject_msg_column_number = -1;
   17124          70 :   promise_reject_line_number = -1;
   17125          70 :   promise_reject_column_number = -1;
   17126          70 :   promise_reject_frame_count = -1;
   17127             : 
   17128          70 :   v8::Local<v8::Object> global = CcTest::global();
   17129          70 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17130         280 :   global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
   17131         280 :   global->Set(context, v8_str("value"), v8_str("")).FromJust();
   17132         280 :   global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
   17133          70 : }
   17134             : 
   17135             : 
   17136       25880 : TEST(PromiseRejectCallback) {
   17137           5 :   LocalContext env;
   17138           5 :   v8::Isolate* isolate = env->GetIsolate();
   17139          10 :   v8::HandleScope scope(isolate);
   17140             : 
   17141           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17142             : 
   17143           5 :   ResetPromiseStates();
   17144             : 
   17145             :   // Create promise p0.
   17146             :   CompileRun(
   17147             :       "var reject;            \n"
   17148             :       "var p0 = new Promise(  \n"
   17149             :       "  function(res, rej) { \n"
   17150             :       "    reject = rej;      \n"
   17151             :       "  }                    \n"
   17152             :       ");                     \n");
   17153          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17154           5 :   CHECK_EQ(0, promise_reject_counter);
   17155           5 :   CHECK_EQ(0, promise_revoke_counter);
   17156             : 
   17157             :   // Add resolve handler (and default reject handler) to p0.
   17158             :   CompileRun("var p1 = p0.then(function(){});");
   17159          10 :   CHECK(GetPromise("p0")->HasHandler());
   17160          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17161           5 :   CHECK_EQ(0, promise_reject_counter);
   17162           5 :   CHECK_EQ(0, promise_revoke_counter);
   17163             : 
   17164             :   // Reject p0.
   17165             :   CompileRun("reject('ppp');");
   17166          10 :   CHECK(GetPromise("p0")->HasHandler());
   17167          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17168           5 :   CHECK_EQ(1, promise_reject_counter);
   17169           5 :   CHECK_EQ(0, promise_revoke_counter);
   17170           5 :   CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
   17171          20 :   CHECK(
   17172             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
   17173          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17174             : 
   17175             :   // Reject p0 again. Callback is not triggered again.
   17176             :   CompileRun("reject();");
   17177          10 :   CHECK(GetPromise("p0")->HasHandler());
   17178          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17179           5 :   CHECK_EQ(1, promise_reject_counter);
   17180           5 :   CHECK_EQ(0, promise_revoke_counter);
   17181             : 
   17182             :   // Add resolve handler to p1.
   17183             :   CompileRun("var p2 = p1.then(function(){});");
   17184          10 :   CHECK(GetPromise("p0")->HasHandler());
   17185          10 :   CHECK(GetPromise("p1")->HasHandler());
   17186          10 :   CHECK(!GetPromise("p2")->HasHandler());
   17187           5 :   CHECK_EQ(2, promise_reject_counter);
   17188           5 :   CHECK_EQ(1, promise_revoke_counter);
   17189          20 :   CHECK(
   17190             :       GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
   17191          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
   17192          20 :   CHECK(
   17193             :       GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
   17194             : 
   17195           5 :   ResetPromiseStates();
   17196             : 
   17197             :   // Create promise q0.
   17198             :   CompileRun(
   17199             :       "var q0 = new Promise(  \n"
   17200             :       "  function(res, rej) { \n"
   17201             :       "    reject = rej;      \n"
   17202             :       "  }                    \n"
   17203             :       ");                     \n");
   17204          10 :   CHECK(!GetPromise("q0")->HasHandler());
   17205           5 :   CHECK_EQ(0, promise_reject_counter);
   17206           5 :   CHECK_EQ(0, promise_revoke_counter);
   17207             : 
   17208             :   // Add reject handler to q0.
   17209             :   CompileRun("var q1 = q0.catch(function() {});");
   17210          10 :   CHECK(GetPromise("q0")->HasHandler());
   17211          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17212           5 :   CHECK_EQ(0, promise_reject_counter);
   17213           5 :   CHECK_EQ(0, promise_revoke_counter);
   17214             : 
   17215             :   // Reject q0.
   17216             :   CompileRun("reject('qq')");
   17217          10 :   CHECK(GetPromise("q0")->HasHandler());
   17218          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17219           5 :   CHECK_EQ(0, promise_reject_counter);
   17220           5 :   CHECK_EQ(0, promise_revoke_counter);
   17221             : 
   17222             :   // Add a new reject handler, which rejects by returning Promise.reject().
   17223             :   // The returned promise q_ triggers a reject callback at first, only to
   17224             :   // revoke it when returning it causes q2 to be rejected.
   17225             :   CompileRun(
   17226             :       "var q_;"
   17227             :       "var q2 = q0.catch(               \n"
   17228             :       "   function() {                  \n"
   17229             :       "     q_ = Promise.reject('qqq'); \n"
   17230             :       "     return q_;                  \n"
   17231             :       "   }                             \n"
   17232             :       ");                               \n");
   17233          10 :   CHECK(GetPromise("q0")->HasHandler());
   17234          10 :   CHECK(!GetPromise("q1")->HasHandler());
   17235          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17236          10 :   CHECK(GetPromise("q_")->HasHandler());
   17237           5 :   CHECK_EQ(2, promise_reject_counter);
   17238           5 :   CHECK_EQ(1, promise_revoke_counter);
   17239          20 :   CHECK(
   17240             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
   17241          20 :   CHECK(
   17242             :       GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
   17243          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
   17244             : 
   17245             :   // Add a reject handler to the resolved q1, which rejects by throwing.
   17246             :   CompileRun(
   17247             :       "var q3 = q1.then(  \n"
   17248             :       "   function() {    \n"
   17249             :       "     throw 'qqqq'; \n"
   17250             :       "   }               \n"
   17251             :       ");                 \n");
   17252          10 :   CHECK(GetPromise("q0")->HasHandler());
   17253          10 :   CHECK(GetPromise("q1")->HasHandler());
   17254          10 :   CHECK(!GetPromise("q2")->HasHandler());
   17255          10 :   CHECK(!GetPromise("q3")->HasHandler());
   17256           5 :   CHECK_EQ(3, promise_reject_counter);
   17257           5 :   CHECK_EQ(1, promise_revoke_counter);
   17258          20 :   CHECK(
   17259             :       GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
   17260          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
   17261             : 
   17262           5 :   ResetPromiseStates();
   17263             : 
   17264             :   // Create promise r0, which has three handlers, two of which handle rejects.
   17265             :   CompileRun(
   17266             :       "var r0 = new Promise(             \n"
   17267             :       "  function(res, rej) {            \n"
   17268             :       "    reject = rej;                 \n"
   17269             :       "  }                               \n"
   17270             :       ");                                \n"
   17271             :       "var r1 = r0.catch(function() {}); \n"
   17272             :       "var r2 = r0.then(function() {});  \n"
   17273             :       "var r3 = r0.then(function() {},   \n"
   17274             :       "                 function() {});  \n");
   17275          10 :   CHECK(GetPromise("r0")->HasHandler());
   17276          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17277          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17278          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17279           5 :   CHECK_EQ(0, promise_reject_counter);
   17280           5 :   CHECK_EQ(0, promise_revoke_counter);
   17281             : 
   17282             :   // Reject r0.
   17283             :   CompileRun("reject('rrr')");
   17284          10 :   CHECK(GetPromise("r0")->HasHandler());
   17285          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17286          10 :   CHECK(!GetPromise("r2")->HasHandler());
   17287          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17288           5 :   CHECK_EQ(1, promise_reject_counter);
   17289           5 :   CHECK_EQ(0, promise_revoke_counter);
   17290          20 :   CHECK(
   17291             :       GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
   17292          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17293             : 
   17294             :   // Add reject handler to r2.
   17295             :   CompileRun("var r4 = r2.catch(function() {});");
   17296          10 :   CHECK(GetPromise("r0")->HasHandler());
   17297          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17298          10 :   CHECK(GetPromise("r2")->HasHandler());
   17299          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17300          10 :   CHECK(!GetPromise("r4")->HasHandler());
   17301           5 :   CHECK_EQ(1, promise_reject_counter);
   17302           5 :   CHECK_EQ(1, promise_revoke_counter);
   17303          20 :   CHECK(
   17304             :       GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
   17305          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
   17306             : 
   17307             :   // Add reject handlers to r4.
   17308             :   CompileRun("var r5 = r4.then(function() {}, function() {});");
   17309          10 :   CHECK(GetPromise("r0")->HasHandler());
   17310          10 :   CHECK(!GetPromise("r1")->HasHandler());
   17311          10 :   CHECK(GetPromise("r2")->HasHandler());
   17312          10 :   CHECK(!GetPromise("r3")->HasHandler());
   17313          10 :   CHECK(GetPromise("r4")->HasHandler());
   17314          10 :   CHECK(!GetPromise("r5")->HasHandler());
   17315           5 :   CHECK_EQ(1, promise_reject_counter);
   17316           5 :   CHECK_EQ(1, promise_revoke_counter);
   17317             : 
   17318           5 :   ResetPromiseStates();
   17319             : 
   17320             :   // Create promise s0, which has three handlers, none of which handle rejects.
   17321             :   CompileRun(
   17322             :       "var s0 = new Promise(            \n"
   17323             :       "  function(res, rej) {           \n"
   17324             :       "    reject = rej;                \n"
   17325             :       "  }                              \n"
   17326             :       ");                               \n"
   17327             :       "var s1 = s0.then(function() {}); \n"
   17328             :       "var s2 = s0.then(function() {}); \n"
   17329             :       "var s3 = s0.then(function() {}); \n");
   17330          10 :   CHECK(GetPromise("s0")->HasHandler());
   17331          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17332          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17333          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17334           5 :   CHECK_EQ(0, promise_reject_counter);
   17335           5 :   CHECK_EQ(0, promise_revoke_counter);
   17336             : 
   17337             :   // Reject s0.
   17338             :   CompileRun("reject('sss')");
   17339          10 :   CHECK(GetPromise("s0")->HasHandler());
   17340          10 :   CHECK(!GetPromise("s1")->HasHandler());
   17341          10 :   CHECK(!GetPromise("s2")->HasHandler());
   17342          10 :   CHECK(!GetPromise("s3")->HasHandler());
   17343           5 :   CHECK_EQ(3, promise_reject_counter);
   17344           5 :   CHECK_EQ(0, promise_revoke_counter);
   17345          20 :   CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
   17346             : 
   17347           5 :   ResetPromiseStates();
   17348             : 
   17349             :   // Swallowed exceptions in the Promise constructor.
   17350             :   CompileRun(
   17351             :       "var v0 = new Promise(\n"
   17352             :       "  function(res, rej) {\n"
   17353             :       "    res(1);\n"
   17354             :       "    throw new Error();\n"
   17355             :       "  }\n"
   17356             :       ");\n");
   17357          10 :   CHECK(!GetPromise("v0")->HasHandler());
   17358           5 :   CHECK_EQ(0, promise_reject_counter);
   17359           5 :   CHECK_EQ(0, promise_revoke_counter);
   17360           5 :   CHECK_EQ(1, promise_reject_after_resolved_counter);
   17361           5 :   CHECK_EQ(0, promise_resolve_after_resolved_counter);
   17362             : 
   17363           5 :   ResetPromiseStates();
   17364             : 
   17365             :   // Duplication resolve.
   17366             :   CompileRun(
   17367             :       "var r;\n"
   17368             :       "var y0 = new Promise(\n"
   17369             :       "  function(res, rej) {\n"
   17370             :       "    r = res;\n"
   17371             :       "    throw new Error();\n"
   17372             :       "  }\n"
   17373             :       ");\n"
   17374             :       "r(1);\n");
   17375          10 :   CHECK(!GetPromise("y0")->HasHandler());
   17376           5 :   CHECK_EQ(1, promise_reject_counter);
   17377           5 :   CHECK_EQ(0, promise_revoke_counter);
   17378           5 :   CHECK_EQ(0, promise_reject_after_resolved_counter);
   17379           5 :   CHECK_EQ(1, promise_resolve_after_resolved_counter);
   17380             : 
   17381             :   // Test stack frames.
   17382           5 :   env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
   17383             : 
   17384           5 :   ResetPromiseStates();
   17385             : 
   17386             :   // Create promise t0, which is rejected in the constructor with an error.
   17387             :   CompileRunWithOrigin(
   17388             :       "var t0 = new Promise(  \n"
   17389             :       "  function(res, rej) { \n"
   17390             :       "    reference_error;   \n"
   17391             :       "  }                    \n"
   17392             :       ");                     \n",
   17393           5 :       "pro", 0, 0);
   17394          10 :   CHECK(!GetPromise("t0")->HasHandler());
   17395           5 :   CHECK_EQ(1, promise_reject_counter);
   17396           5 :   CHECK_EQ(0, promise_revoke_counter);
   17397           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17398           5 :   CHECK_EQ(3, promise_reject_line_number);
   17399           5 :   CHECK_EQ(5, promise_reject_column_number);
   17400           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   17401           5 :   CHECK_EQ(5, promise_reject_msg_column_number);
   17402             : 
   17403           5 :   ResetPromiseStates();
   17404             : 
   17405             :   // Create promise u0 and chain u1 to it, which is rejected via throw.
   17406             :   CompileRunWithOrigin(
   17407             :       "var u0 = Promise.resolve();        \n"
   17408             :       "var u1 = u0.then(                  \n"
   17409             :       "           function() {            \n"
   17410             :       "             (function() {         \n"
   17411             :       "                throw new Error(); \n"
   17412             :       "              })();                \n"
   17413             :       "           }                       \n"
   17414             :       "         );                        \n",
   17415           5 :       "pro", 0, 0);
   17416          10 :   CHECK(GetPromise("u0")->HasHandler());
   17417          10 :   CHECK(!GetPromise("u1")->HasHandler());
   17418           5 :   CHECK_EQ(1, promise_reject_counter);
   17419           5 :   CHECK_EQ(0, promise_revoke_counter);
   17420           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17421           5 :   CHECK_EQ(5, promise_reject_line_number);
   17422           5 :   CHECK_EQ(23, promise_reject_column_number);
   17423           5 :   CHECK_EQ(5, promise_reject_msg_line_number);
   17424           5 :   CHECK_EQ(23, promise_reject_msg_column_number);
   17425             : 
   17426             :   // Throw in u3, which handles u1's rejection.
   17427             :   CompileRunWithOrigin(
   17428             :       "function f() {                \n"
   17429             :       "  return (function() {        \n"
   17430             :       "    return new Error();       \n"
   17431             :       "  })();                       \n"
   17432             :       "}                             \n"
   17433             :       "var u2 = Promise.reject(f()); \n"
   17434             :       "var u3 = u1.catch(            \n"
   17435             :       "           function() {       \n"
   17436             :       "             return u2;       \n"
   17437             :       "           }                  \n"
   17438             :       "         );                   \n",
   17439           5 :       "pro", 0, 0);
   17440          10 :   CHECK(GetPromise("u0")->HasHandler());
   17441          10 :   CHECK(GetPromise("u1")->HasHandler());
   17442          10 :   CHECK(GetPromise("u2")->HasHandler());
   17443          10 :   CHECK(!GetPromise("u3")->HasHandler());
   17444           5 :   CHECK_EQ(3, promise_reject_counter);
   17445           5 :   CHECK_EQ(2, promise_revoke_counter);
   17446           5 :   CHECK_EQ(3, promise_reject_frame_count);
   17447           5 :   CHECK_EQ(3, promise_reject_line_number);
   17448           5 :   CHECK_EQ(12, promise_reject_column_number);
   17449           5 :   CHECK_EQ(3, promise_reject_msg_line_number);
   17450           5 :   CHECK_EQ(12, promise_reject_msg_column_number);
   17451             : 
   17452           5 :   ResetPromiseStates();
   17453             : 
   17454             :   // Create promise rejected promise v0, which is incorrectly handled by v1
   17455             :   // via chaining cycle.
   17456             :   CompileRunWithOrigin(
   17457             :       "var v0 = Promise.reject(); \n"
   17458             :       "var v1 = v0.catch(         \n"
   17459             :       "           function() {    \n"
   17460             :       "             return v1;    \n"
   17461             :       "           }               \n"
   17462             :       "         );                \n",
   17463           5 :       "pro", 0, 0);
   17464          10 :   CHECK(GetPromise("v0")->HasHandler());
   17465          10 :   CHECK(!GetPromise("v1")->HasHandler());
   17466           5 :   CHECK_EQ(2, promise_reject_counter);
   17467           5 :   CHECK_EQ(1, promise_revoke_counter);
   17468           5 :   CHECK_EQ(0, promise_reject_frame_count);
   17469           5 :   CHECK_EQ(-1, promise_reject_line_number);
   17470           5 :   CHECK_EQ(-1, promise_reject_column_number);
   17471             : 
   17472           5 :   ResetPromiseStates();
   17473             : 
   17474             :   // Create promise t1, which rejects by throwing syntax error from eval.
   17475             :   CompileRunWithOrigin(
   17476             :       "var t1 = new Promise(   \n"
   17477             :       "  function(res, rej) {  \n"
   17478             :       "    var content = '\\n\\\n"
   17479             :       "      }';               \n"
   17480             :       "    eval(content);      \n"
   17481             :       "  }                     \n"
   17482             :       ");                      \n",
   17483           5 :       "pro", 0, 0);
   17484          10 :   CHECK(!GetPromise("t1")->HasHandler());
   17485           5 :   CHECK_EQ(1, promise_reject_counter);
   17486           5 :   CHECK_EQ(0, promise_revoke_counter);
   17487           5 :   CHECK_EQ(2, promise_reject_frame_count);
   17488           5 :   CHECK_EQ(5, promise_reject_line_number);
   17489           5 :   CHECK_EQ(10, promise_reject_column_number);
   17490           5 :   CHECK_EQ(2, promise_reject_msg_line_number);
   17491          10 :   CHECK_EQ(7, promise_reject_msg_column_number);
   17492           5 : }
   17493             : 
   17494       25880 : TEST(PromiseRejectIsSharedCrossOrigin) {
   17495           5 :   LocalContext env;
   17496           5 :   v8::Isolate* isolate = env->GetIsolate();
   17497          10 :   v8::HandleScope scope(isolate);
   17498             : 
   17499           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17500             : 
   17501           5 :   ResetPromiseStates();
   17502             : 
   17503             :   // Create promise p0.
   17504             :   CompileRun(
   17505             :       "var reject;            \n"
   17506             :       "var p0 = new Promise(  \n"
   17507             :       "  function(res, rej) { \n"
   17508             :       "    reject = rej;      \n"
   17509             :       "  }                    \n"
   17510             :       ");                     \n");
   17511          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17512           5 :   CHECK_EQ(0, promise_reject_counter);
   17513           5 :   CHECK_EQ(0, promise_revoke_counter);
   17514             :   // Not set because it's not yet rejected.
   17515           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   17516             : 
   17517             :   // Reject p0.
   17518             :   CompileRun("reject('ppp');");
   17519           5 :   CHECK_EQ(1, promise_reject_counter);
   17520           5 :   CHECK_EQ(0, promise_revoke_counter);
   17521             :   // Not set because the ScriptOriginOptions is from the script.
   17522           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   17523             : 
   17524           5 :   ResetPromiseStates();
   17525             : 
   17526             :   // Create promise p1
   17527             :   CompileRun(
   17528             :       "var reject;            \n"
   17529             :       "var p1 = new Promise(  \n"
   17530             :       "  function(res, rej) { \n"
   17531             :       "    reject = rej;      \n"
   17532             :       "  }                    \n"
   17533             :       ");                     \n");
   17534          10 :   CHECK(!GetPromise("p1")->HasHandler());
   17535           5 :   CHECK_EQ(0, promise_reject_counter);
   17536           5 :   CHECK_EQ(0, promise_revoke_counter);
   17537             :   // Not set because it's not yet rejected.
   17538           5 :   CHECK(!promise_reject_is_shared_cross_origin);
   17539             : 
   17540             :   // Add resolve handler (and default reject handler) to p1.
   17541             :   CompileRun("var p2 = p1.then(function(){});");
   17542          10 :   CHECK(GetPromise("p1")->HasHandler());
   17543          10 :   CHECK(!GetPromise("p2")->HasHandler());
   17544           5 :   CHECK_EQ(0, promise_reject_counter);
   17545           5 :   CHECK_EQ(0, promise_revoke_counter);
   17546             : 
   17547             :   // Reject p1.
   17548             :   CompileRun("reject('ppp');");
   17549           5 :   CHECK_EQ(1, promise_reject_counter);
   17550           5 :   CHECK_EQ(0, promise_revoke_counter);
   17551             :   // Set because the event is from an empty script.
   17552          10 :   CHECK(promise_reject_is_shared_cross_origin);
   17553           5 : }
   17554             : 
   17555       25880 : TEST(PromiseRejectMarkAsHandled) {
   17556           5 :   LocalContext env;
   17557           5 :   v8::Isolate* isolate = env->GetIsolate();
   17558          10 :   v8::HandleScope scope(isolate);
   17559             : 
   17560           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallback);
   17561             : 
   17562           5 :   ResetPromiseStates();
   17563             : 
   17564             :   // Create promise p0.
   17565             :   CompileRun(
   17566             :       "var reject;            \n"
   17567             :       "var p0 = new Promise(  \n"
   17568             :       "  function(res, rej) { \n"
   17569             :       "    reject = rej;      \n"
   17570             :       "  }                    \n"
   17571             :       ");                     \n");
   17572          10 :   CHECK(!GetPromise("p0")->HasHandler());
   17573           5 :   CHECK_EQ(0, promise_reject_counter);
   17574           5 :   CHECK_EQ(0, promise_revoke_counter);
   17575          10 :   GetPromise("p0")->MarkAsHandled();
   17576             : 
   17577             :   // Reject p0. promise_reject_counter shouldn't be incremented because
   17578             :   // it's marked as handled.
   17579             :   CompileRun("reject('ppp');");
   17580           5 :   CHECK_EQ(0, promise_reject_counter);
   17581          10 :   CHECK_EQ(0, promise_revoke_counter);
   17582           5 : }
   17583          30 : void PromiseRejectCallbackConstructError(
   17584             :     v8::PromiseRejectMessage reject_message) {
   17585          30 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17586          30 :   CHECK_EQ(v8::Promise::PromiseState::kRejected,
   17587             :            reject_message.GetPromise()->State());
   17588          60 :   USE(v8::Script::Compile(context, v8_str("new Error('test')"))
   17589             :           .ToLocalChecked()
   17590             :           ->Run(context));
   17591          30 : }
   17592             : 
   17593       25880 : TEST(PromiseRejectCallbackConstructError) {
   17594           5 :   i::FLAG_allow_natives_syntax = true;
   17595           5 :   LocalContext env;
   17596           5 :   v8::Isolate* isolate = env->GetIsolate();
   17597          10 :   v8::HandleScope scope(isolate);
   17598             : 
   17599           5 :   isolate->SetPromiseRejectCallback(PromiseRejectCallbackConstructError);
   17600             : 
   17601           5 :   ResetPromiseStates();
   17602             :   CompileRun(
   17603             :       "function f(p) {"
   17604             :       "    p.catch(() => {});"
   17605             :       "}"
   17606             :       "f(Promise.reject());"
   17607             :       "f(Promise.reject());"
   17608             :       "%OptimizeFunctionOnNextCall(f);"
   17609             :       "let p = Promise.reject();"
   17610           5 :       "f(p);");
   17611           5 : }
   17612             : 
   17613          10 : void AnalyzeStackOfEvalWithSourceURL(
   17614          80 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17615          10 :   v8::HandleScope scope(args.GetIsolate());
   17616             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17617          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17618          10 :   CHECK_EQ(5, stackTrace->GetFrameCount());
   17619          10 :   v8::Local<v8::String> url = v8_str("eval_url");
   17620          40 :   for (int i = 0; i < 3; i++) {
   17621             :     v8::Local<v8::String> name =
   17622          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   17623          30 :     CHECK(!name.IsEmpty());
   17624          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17625          10 :   }
   17626          10 : }
   17627             : 
   17628             : 
   17629       25880 : TEST(SourceURLInStackTrace) {
   17630           5 :   v8::Isolate* isolate = CcTest::isolate();
   17631           5 :   v8::HandleScope scope(isolate);
   17632           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17633             :   templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
   17634             :              v8::FunctionTemplate::New(isolate,
   17635          15 :                                        AnalyzeStackOfEvalWithSourceURL));
   17636          10 :   LocalContext context(nullptr, templ);
   17637             : 
   17638             :   const char *source =
   17639             :     "function outer() {\n"
   17640             :     "function bar() {\n"
   17641             :     "  AnalyzeStackOfEvalWithSourceURL();\n"
   17642             :     "}\n"
   17643             :     "function foo() {\n"
   17644             :     "\n"
   17645             :     "  bar();\n"
   17646             :     "}\n"
   17647             :     "foo();\n"
   17648             :     "}\n"
   17649             :     "eval('(' + outer +')()%s');";
   17650             : 
   17651             :   i::ScopedVector<char> code(1024);
   17652           5 :   i::SNPrintF(code, source, "//# sourceURL=eval_url");
   17653           5 :   CHECK(CompileRun(code.start())->IsUndefined());
   17654           5 :   i::SNPrintF(code, source, "//@ sourceURL=eval_url");
   17655          10 :   CHECK(CompileRun(code.start())->IsUndefined());
   17656           5 : }
   17657             : 
   17658             : 
   17659             : static int scriptIdInStack[2];
   17660             : 
   17661           5 : void AnalyzeScriptIdInStack(
   17662          20 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17663           5 :   v8::HandleScope scope(args.GetIsolate());
   17664             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17665           5 :       args.GetIsolate(), 10, v8::StackTrace::kScriptId);
   17666           5 :   CHECK_EQ(2, stackTrace->GetFrameCount());
   17667          10 :   for (int i = 0; i < 2; i++) {
   17668             :     scriptIdInStack[i] =
   17669          30 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptId();
   17670           5 :   }
   17671           5 : }
   17672             : 
   17673             : 
   17674       25880 : TEST(ScriptIdInStackTrace) {
   17675           5 :   v8::Isolate* isolate = CcTest::isolate();
   17676           5 :   v8::HandleScope scope(isolate);
   17677           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17678             :   templ->Set(v8_str("AnalyzeScriptIdInStack"),
   17679          15 :              v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
   17680          10 :   LocalContext context(nullptr, templ);
   17681             : 
   17682             :   v8::Local<v8::String> scriptSource = v8_str(
   17683             :       "function foo() {\n"
   17684             :       "  AnalyzeScriptIdInStack();"
   17685             :       "}\n"
   17686           5 :       "foo();\n");
   17687             :   v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
   17688           5 :   script->Run(context.local()).ToLocalChecked();
   17689          15 :   for (int i = 0; i < 2; i++) {
   17690          10 :     CHECK_NE(scriptIdInStack[i], v8::Message::kNoScriptIdInfo);
   17691          20 :     CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
   17692           5 :   }
   17693           5 : }
   17694             : 
   17695             : 
   17696          10 : void AnalyzeStackOfInlineScriptWithSourceURL(
   17697          80 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   17698          10 :   v8::HandleScope scope(args.GetIsolate());
   17699             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   17700          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   17701          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   17702          10 :   v8::Local<v8::String> url = v8_str("source_url");
   17703          40 :   for (int i = 0; i < 3; i++) {
   17704             :     v8::Local<v8::String> name =
   17705          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   17706          30 :     CHECK(!name.IsEmpty());
   17707          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   17708          10 :   }
   17709          10 : }
   17710             : 
   17711             : 
   17712       25880 : TEST(InlineScriptWithSourceURLInStackTrace) {
   17713           5 :   v8::Isolate* isolate = CcTest::isolate();
   17714           5 :   v8::HandleScope scope(isolate);
   17715           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   17716             :   templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
   17717             :              v8::FunctionTemplate::New(
   17718          15 :                  CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
   17719          10 :   LocalContext context(nullptr, templ);
   17720             : 
   17721             :   const char *source =
   17722             :     "function outer() {\n"
   17723             :     "function bar() {\n"
   17724             :     "  AnalyzeStackOfInlineScriptWithSourceURL();\n"
   17725             :     "}\n"
   17726             :     "function foo() {\n"
   17727             :     "\n"
   17728             :     "  bar();\n"
   17729             :     "}\n"
   17730             :     "foo();\n"
   17731             :     "}\n"
   17732             :     "outer()\n%s";
   17733             : 
   17734             :   i::ScopedVector<char> code(1024);
   17735           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   17736          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17737           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   17738          15 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
   17739           5 : }
   17740             : 
   17741         395 : void SetPromise(const char* name, v8::Local<v8::Promise> promise) {
   17742             :   CcTest::global()
   17743        1185 :       ->Set(CcTest::isolate()->GetCurrentContext(), v8_str(name), promise)
   17744         790 :       .FromJust();
   17745         395 : }
   17746             : 
   17747           5 : class PromiseHookData {
   17748             :  public:
   17749             :   int before_hook_count = 0;
   17750             :   int after_hook_count = 0;
   17751             :   int promise_hook_count = 0;
   17752             :   int parent_promise_count = 0;
   17753             :   bool check_value = true;
   17754             :   std::string promise_hook_value;
   17755             : 
   17756             :   void Reset() {
   17757          50 :     before_hook_count = 0;
   17758          50 :     after_hook_count = 0;
   17759          50 :     promise_hook_count = 0;
   17760          50 :     parent_promise_count = 0;
   17761          50 :     check_value = true;
   17762          50 :     promise_hook_value = "";
   17763             :   }
   17764             : };
   17765             : 
   17766             : PromiseHookData* promise_hook_data;
   17767             : 
   17768         350 : void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise,
   17769             :                        v8::Local<v8::Value> parentPromise) {
   17770         350 :   promise_hook_data->promise_hook_count++;
   17771         350 :   switch (type) {
   17772             :     case v8::PromiseHookType::kInit:
   17773         125 :       SetPromise("init", promise);
   17774             : 
   17775         125 :       if (!parentPromise->IsUndefined()) {
   17776          45 :         promise_hook_data->parent_promise_count++;
   17777          45 :         SetPromise("parent", v8::Local<v8::Promise>::Cast(parentPromise));
   17778             :       }
   17779             : 
   17780             :       break;
   17781             :     case v8::PromiseHookType::kResolve:
   17782         125 :       SetPromise("resolve", promise);
   17783         125 :       break;
   17784             :     case v8::PromiseHookType::kBefore:
   17785          50 :       promise_hook_data->before_hook_count++;
   17786          50 :       CHECK(promise_hook_data->before_hook_count >
   17787             :             promise_hook_data->after_hook_count);
   17788         300 :       CHECK(CcTest::global()
   17789             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17790             :                 .ToLocalChecked()
   17791             :                 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str(""))
   17792             :                 .FromJust());
   17793          50 :       SetPromise("before", promise);
   17794          50 :       break;
   17795             :     case v8::PromiseHookType::kAfter:
   17796          50 :       promise_hook_data->after_hook_count++;
   17797          50 :       CHECK(promise_hook_data->after_hook_count <=
   17798             :             promise_hook_data->before_hook_count);
   17799          50 :       if (promise_hook_data->check_value) {
   17800         180 :         CHECK(
   17801             :             CcTest::global()
   17802             :                 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   17803             :                 .ToLocalChecked()
   17804             :                 ->Equals(CcTest::isolate()->GetCurrentContext(),
   17805             :                          v8_str(promise_hook_data->promise_hook_value.c_str()))
   17806             :                 .FromJust());
   17807             :       }
   17808          50 :       SetPromise("after", promise);
   17809          50 :       break;
   17810             :   }
   17811         350 : }
   17812             : 
   17813       25880 : TEST(PromiseHook) {
   17814           5 :   LocalContext env;
   17815           5 :   v8::Isolate* isolate = env->GetIsolate();
   17816          10 :   v8::HandleScope scope(isolate);
   17817             : 
   17818           5 :   v8::Local<v8::Object> global = CcTest::global();
   17819           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   17820             : 
   17821          10 :   promise_hook_data = new PromiseHookData();
   17822           5 :   isolate->SetPromiseHook(CustomPromiseHook);
   17823             : 
   17824             :   // Test that an initialized promise is passed to init. Other hooks
   17825             :   // can not have un initialized promise.
   17826           5 :   promise_hook_data->check_value = false;
   17827             :   CompileRun("var p = new Promise(() => {});");
   17828             : 
   17829          15 :   auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17830          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17831             :   auto init_promise_obj = v8::Local<v8::Promise>::Cast(init_promise);
   17832           5 :   CHECK_EQ(init_promise_obj->State(), v8::Promise::PromiseState::kPending);
   17833           5 :   CHECK(!init_promise_obj->HasHandler());
   17834             : 
   17835           5 :   promise_hook_data->Reset();
   17836           5 :   promise_hook_data->promise_hook_value = "fulfilled";
   17837             :   const char* source =
   17838             :       "var resolve, value = ''; \n"
   17839             :       "var p = new Promise(r => resolve = r); \n";
   17840             : 
   17841             :   CompileRun(source);
   17842          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17843          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17844           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17845           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17846             : 
   17847             :   CompileRun("var p1 = p.then(() => { value = 'fulfilled'; }); \n");
   17848          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17849          15 :   auto parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17850          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   17851          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   17852           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17853           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   17854             : 
   17855             :   CompileRun("resolve(); \n");
   17856             :   auto resolve_promise =
   17857          15 :       global->Get(context, v8_str("resolve")).ToLocalChecked();
   17858          15 :   auto before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17859          15 :   auto after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17860          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   17861          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   17862          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17863           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   17864             : 
   17865             :   CompileRun("value = ''; var p2 = p1.then(() => { value = 'fulfilled' }); \n");
   17866          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17867          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17868          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17869          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17870          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17871          15 :   CHECK(GetPromise("p2")->Equals(env.local(), init_promise).FromJust());
   17872          15 :   CHECK(GetPromise("p1")->Equals(env.local(), parent_promise).FromJust());
   17873          15 :   CHECK(GetPromise("p2")->Equals(env.local(), before_promise).FromJust());
   17874          15 :   CHECK(GetPromise("p2")->Equals(env.local(), after_promise).FromJust());
   17875          15 :   CHECK(GetPromise("p2")->Equals(env.local(), resolve_promise).FromJust());
   17876           5 :   CHECK_EQ(10, promise_hook_data->promise_hook_count);
   17877             : 
   17878             :   promise_hook_data->Reset();
   17879           5 :   promise_hook_data->promise_hook_value = "rejected";
   17880             :   source =
   17881             :       "var reject, value = ''; \n"
   17882             :       "var p = new Promise((_, r) => reject = r); \n";
   17883             : 
   17884             :   CompileRun(source);
   17885          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17886          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17887           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17888           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17889             : 
   17890             :   CompileRun("var p1 = p.catch(() => { value = 'rejected'; }); \n");
   17891          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17892          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17893          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   17894          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   17895           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17896           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   17897             : 
   17898             :   CompileRun("reject(); \n");
   17899          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17900          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17901          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17902          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   17903          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   17904          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17905           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   17906             : 
   17907             :   promise_hook_data->Reset();
   17908           5 :   promise_hook_data->promise_hook_value = "Promise.resolve";
   17909             :   source =
   17910             :       "var value = ''; \n"
   17911             :       "var p = Promise.resolve('Promise.resolve'); \n";
   17912             : 
   17913             :   CompileRun(source);
   17914          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17915          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17916             :   // init hook and resolve hook
   17917           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17918           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17919          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17920          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   17921             : 
   17922             :   CompileRun("var p1 = p.then((v) => { value = v; }); \n");
   17923          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17924          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17925          15 :   parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked();
   17926          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   17927          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   17928          15 :   CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust());
   17929          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17930          15 :   CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust());
   17931          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   17932          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   17933           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   17934           5 :   CHECK_EQ(1, promise_hook_data->parent_promise_count);
   17935             : 
   17936             :   promise_hook_data->Reset();
   17937             :   source =
   17938             :       "var resolve, value = ''; \n"
   17939             :       "var p = new Promise((_, r) => resolve = r); \n";
   17940             : 
   17941             :   CompileRun(source);
   17942          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17943          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17944           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17945           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17946             : 
   17947             :   CompileRun("resolve(); \n");
   17948          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17949          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   17950           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17951             : 
   17952             :   promise_hook_data->Reset();
   17953             :   source =
   17954             :       "var reject, value = ''; \n"
   17955             :       "var p = new Promise((_, r) => reject = r); \n";
   17956             : 
   17957             :   CompileRun(source);
   17958          15 :   init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
   17959          15 :   CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
   17960           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   17961           5 :   CHECK_EQ(0, promise_hook_data->parent_promise_count);
   17962             : 
   17963             :   CompileRun("reject(); \n");
   17964          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17965          15 :   CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust());
   17966           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   17967             : 
   17968             :   promise_hook_data->Reset();
   17969             :   // This test triggers after callbacks right after each other, so
   17970             :   // lets just check the value at the end.
   17971           5 :   promise_hook_data->check_value = false;
   17972           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   17973             :   source =
   17974             :       "var resolve, value = ''; \n"
   17975             :       "var tempPromise = new Promise(r => resolve = r); \n"
   17976             :       "var p = Promise.all([tempPromise]);\n "
   17977             :       "var p1 = p.then(v => value = v[0]); \n";
   17978             : 
   17979             :   CompileRun(source);
   17980             :   // 1) init hook (tempPromise)
   17981             :   // 2) init hook (p)
   17982             :   // 3) init hook (throwaway Promise in Promise.all, p)
   17983             :   // 4) init hook (p1, p)
   17984           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   17985           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   17986             : 
   17987           5 :   promise_hook_data->promise_hook_value = "Promise.all";
   17988             :   CompileRun("resolve('Promise.all'); \n");
   17989          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   17990          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   17991             :   // 5) resolve hook (tempPromise)
   17992             :   // 6) resolve hook (throwaway Promise in Promise.all)
   17993             :   // 6) before hook (throwaway Promise in Promise.all)
   17994             :   // 7) after hook (throwaway Promise in Promise.all)
   17995             :   // 8) before hook (p)
   17996             :   // 9) after hook (p)
   17997             :   // 10) resolve hook (p1)
   17998             :   // 11) before hook (p1)
   17999             :   // 12) after hook (p1)
   18000           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   18001          30 :   CHECK(CcTest::global()
   18002             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18003             :             .ToLocalChecked()
   18004             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   18005             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   18006             :             .FromJust());
   18007             : 
   18008           5 :   promise_hook_data->Reset();
   18009             :   // This test triggers after callbacks right after each other, so
   18010             :   // lets just check the value at the end.
   18011           5 :   promise_hook_data->check_value = false;
   18012           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   18013             :   source =
   18014             :       "var resolve, value = ''; \n"
   18015             :       "var tempPromise = new Promise(r => resolve = r); \n"
   18016             :       "var p = Promise.race([tempPromise]);\n "
   18017             :       "var p1 = p.then(v => value = v); \n";
   18018             : 
   18019             :   CompileRun(source);
   18020             :   // 1) init hook (tempPromise)
   18021             :   // 2) init hook (p)
   18022             :   // 3) init hook (throwaway Promise in Promise.race, p)
   18023             :   // 4) init hook (p1, p)
   18024           5 :   CHECK_EQ(4, promise_hook_data->promise_hook_count);
   18025           5 :   CHECK_EQ(2, promise_hook_data->parent_promise_count);
   18026             : 
   18027           5 :   promise_hook_data->promise_hook_value = "Promise.race";
   18028             :   CompileRun("resolve('Promise.race'); \n");
   18029          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18030          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18031             :   // 5) resolve hook (tempPromise)
   18032             :   // 6) resolve hook (throwaway Promise in Promise.race)
   18033             :   // 6) before hook (throwaway Promise in Promise.race)
   18034             :   // 7) after hook (throwaway Promise in Promise.race)
   18035             :   // 8) before hook (p)
   18036             :   // 9) after hook (p)
   18037             :   // 10) resolve hook (p1)
   18038             :   // 11) before hook (p1)
   18039             :   // 12) after hook (p1)
   18040           5 :   CHECK_EQ(12, promise_hook_data->promise_hook_count);
   18041          30 :   CHECK(CcTest::global()
   18042             :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
   18043             :             .ToLocalChecked()
   18044             :             ->Equals(CcTest::isolate()->GetCurrentContext(),
   18045             :                      v8_str(promise_hook_data->promise_hook_value.c_str()))
   18046             :             .FromJust());
   18047             : 
   18048           5 :   promise_hook_data->Reset();
   18049           5 :   promise_hook_data->promise_hook_value = "subclass";
   18050             :   source =
   18051             :       "var resolve, value = '';\n"
   18052             :       "class MyPromise extends Promise { \n"
   18053             :       "  then(onFulfilled, onRejected) { \n"
   18054             :       "      return super.then(onFulfilled, onRejected); \n"
   18055             :       "  };\n"
   18056             :       "};\n"
   18057             :       "var p = new MyPromise(r => resolve = r);\n";
   18058             : 
   18059             :   CompileRun(source);
   18060             :   // 1) init hook (p)
   18061           5 :   CHECK_EQ(1, promise_hook_data->promise_hook_count);
   18062             : 
   18063             :   CompileRun("var p1 = p.then(() => value = 'subclass');\n");
   18064             :   // 2) init hook (p1)
   18065           5 :   CHECK_EQ(2, promise_hook_data->promise_hook_count);
   18066             : 
   18067             :   CompileRun("resolve();\n");
   18068          15 :   resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked();
   18069          15 :   before_promise = global->Get(context, v8_str("before")).ToLocalChecked();
   18070          15 :   after_promise = global->Get(context, v8_str("after")).ToLocalChecked();
   18071          15 :   CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust());
   18072          15 :   CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust());
   18073          15 :   CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust());
   18074             :   // 3) resolve hook (p)
   18075             :   // 4) before hook (p)
   18076             :   // 5) after hook (p)
   18077             :   // 6) resolve hook (p1)
   18078           5 :   CHECK_EQ(6, promise_hook_data->promise_hook_count);
   18079             : 
   18080             :   promise_hook_data->Reset();
   18081             :   source =
   18082             :       "class X extends Promise {\n"
   18083             :       "  static get [Symbol.species]() {\n"
   18084             :       "    return Y;\n"
   18085             :       "  }\n"
   18086             :       "}\n"
   18087             :       "class Y {\n"
   18088             :       "  constructor(executor) {\n"
   18089             :       "    return new Proxy(new Promise(executor), {});\n"
   18090             :       "  }\n"
   18091             :       "}\n"
   18092             :       "var x = X.resolve().then(() => {});\n";
   18093             : 
   18094             :   CompileRun(source);
   18095             : 
   18096           5 :   promise_hook_data->Reset();
   18097             :   source =
   18098             :       "var resolve, value = '';\n"
   18099             :       "var p = new Promise(r => resolve = r);\n";
   18100             : 
   18101             :   CompileRun(source);
   18102          10 :   CHECK_EQ(v8::Promise::kPending, GetPromise("p")->State());
   18103             :   CompileRun("resolve(Promise.resolve(value));\n");
   18104          10 :   CHECK_EQ(v8::Promise::kFulfilled, GetPromise("p")->State());
   18105           5 :   CHECK_EQ(9, promise_hook_data->promise_hook_count);
   18106             : 
   18107          10 :   delete promise_hook_data;
   18108          10 :   isolate->SetPromiseHook(nullptr);
   18109           5 : }
   18110             : 
   18111          10 : void AnalyzeStackOfDynamicScriptWithSourceURL(
   18112          80 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18113          10 :   v8::HandleScope scope(args.GetIsolate());
   18114             :   v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
   18115          10 :       args.GetIsolate(), 10, v8::StackTrace::kDetailed);
   18116          10 :   CHECK_EQ(4, stackTrace->GetFrameCount());
   18117          10 :   v8::Local<v8::String> url = v8_str("source_url");
   18118          40 :   for (int i = 0; i < 3; i++) {
   18119             :     v8::Local<v8::String> name =
   18120          90 :         stackTrace->GetFrame(args.GetIsolate(), i)->GetScriptNameOrSourceURL();
   18121          30 :     CHECK(!name.IsEmpty());
   18122          90 :     CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
   18123          10 :   }
   18124          10 : }
   18125             : 
   18126             : 
   18127       25880 : TEST(DynamicWithSourceURLInStackTrace) {
   18128           5 :   v8::Isolate* isolate = CcTest::isolate();
   18129           5 :   v8::HandleScope scope(isolate);
   18130           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   18131             :   templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
   18132             :              v8::FunctionTemplate::New(
   18133          15 :                  CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
   18134          10 :   LocalContext context(nullptr, templ);
   18135             : 
   18136             :   const char *source =
   18137             :     "function outer() {\n"
   18138             :     "function bar() {\n"
   18139             :     "  AnalyzeStackOfDynamicScriptWithSourceURL();\n"
   18140             :     "}\n"
   18141             :     "function foo() {\n"
   18142             :     "\n"
   18143             :     "  bar();\n"
   18144             :     "}\n"
   18145             :     "foo();\n"
   18146             :     "}\n"
   18147             :     "outer()\n%s";
   18148             : 
   18149             :   i::ScopedVector<char> code(1024);
   18150           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18151          10 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18152           5 :   i::SNPrintF(code, source, "//@ sourceURL=source_url");
   18153          15 :   CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
   18154           5 : }
   18155             : 
   18156             : 
   18157       25880 : TEST(DynamicWithSourceURLInStackTraceString) {
   18158           5 :   LocalContext context;
   18159          10 :   v8::HandleScope scope(context->GetIsolate());
   18160             : 
   18161             :   const char *source =
   18162             :     "function outer() {\n"
   18163             :     "  function foo() {\n"
   18164             :     "    FAIL.FAIL;\n"
   18165             :     "  }\n"
   18166             :     "  foo();\n"
   18167             :     "}\n"
   18168             :     "outer()\n%s";
   18169             : 
   18170             :   i::ScopedVector<char> code(1024);
   18171           5 :   i::SNPrintF(code, source, "//# sourceURL=source_url");
   18172          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18173           5 :   CompileRunWithOrigin(code.start(), "", 0, 0);
   18174           5 :   CHECK(try_catch.HasCaught());
   18175             :   v8::String::Utf8Value stack(
   18176             :       context->GetIsolate(),
   18177          15 :       try_catch.StackTrace(context.local()).ToLocalChecked());
   18178          15 :   CHECK_NOT_NULL(strstr(*stack, "at foo (source_url:3:5)"));
   18179           5 : }
   18180             : 
   18181             : 
   18182       25880 : TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18183           5 :   LocalContext context;
   18184          10 :   v8::HandleScope scope(context->GetIsolate());
   18185             : 
   18186             :   const char *source =
   18187             :     "function outer() {\n"
   18188             :     "  var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
   18189             :     "  //# sourceURL=source_url\";\n"
   18190             :     "  eval(scriptContents);\n"
   18191             :     "  foo(); }\n"
   18192             :     "outer();\n"
   18193             :     "//# sourceURL=outer_url";
   18194             : 
   18195          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18196             :   CompileRun(source);
   18197           5 :   CHECK(try_catch.HasCaught());
   18198             : 
   18199           5 :   Local<v8::Message> message = try_catch.Message();
   18200           5 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18201           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18202           5 :                      "source_url"));
   18203           5 : }
   18204             : 
   18205             : 
   18206       25880 : TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
   18207           5 :   LocalContext context;
   18208          10 :   v8::HandleScope scope(context->GetIsolate());
   18209             : 
   18210             :   const char *source =
   18211             :     "function outer() {\n"
   18212             :     "  var scriptContents = \"function boo(){ boo(); }\\\n"
   18213             :     "  //# sourceURL=source_url\";\n"
   18214             :     "  eval(scriptContents);\n"
   18215             :     "  boo(); }\n"
   18216             :     "outer();\n"
   18217             :     "//# sourceURL=outer_url";
   18218             : 
   18219          10 :   v8::TryCatch try_catch(context->GetIsolate());
   18220             :   CompileRun(source);
   18221           5 :   CHECK(try_catch.HasCaught());
   18222             : 
   18223           5 :   Local<v8::Message> message = try_catch.Message();
   18224           5 :   Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
   18225           5 :   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(context->GetIsolate(), sourceURL),
   18226           5 :                      "source_url"));
   18227           5 : }
   18228             : 
   18229             : 
   18230           5 : static void CreateGarbageInOldSpace() {
   18231             :   i::Factory* factory = CcTest::i_isolate()->factory();
   18232           5 :   v8::HandleScope scope(CcTest::isolate());
   18233             :   i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   18234        5005 :   for (int i = 0; i < 1000; i++) {
   18235        5000 :     factory->NewFixedArray(1000, i::TENURED);
   18236           5 :   }
   18237           5 : }
   18238             : 
   18239             : 
   18240             : // Test that idle notification can be handled and eventually collects garbage.
   18241       25880 : TEST(TestIdleNotification) {
   18242           5 :   if (!i::FLAG_incremental_marking) return;
   18243             :   ManualGCScope manual_gc_scope;
   18244             :   const intptr_t MB = 1024 * 1024;
   18245             :   const double IdlePauseInSeconds = 1.0;
   18246          10 :   LocalContext env;
   18247          10 :   v8::HandleScope scope(env->GetIsolate());
   18248           5 :   intptr_t initial_size = CcTest::heap()->SizeOfObjects();
   18249           5 :   CreateGarbageInOldSpace();
   18250           5 :   intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
   18251           5 :   CHECK_GT(size_with_garbage, initial_size + MB);
   18252             :   bool finished = false;
   18253          35 :   for (int i = 0; i < 200 && !finished; i++) {
   18254          70 :     if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
   18255             :       CcTest::heap()->StartIdleIncrementalMarking(
   18256           5 :           i::GarbageCollectionReason::kTesting);
   18257             :     }
   18258             :     finished = env->GetIsolate()->IdleNotificationDeadline(
   18259         105 :         (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
   18260             :          static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
   18261          70 :         IdlePauseInSeconds);
   18262         105 :     if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
   18263          10 :       CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
   18264             :     }
   18265             :   }
   18266           5 :   intptr_t final_size = CcTest::heap()->SizeOfObjects();
   18267           5 :   CHECK(finished);
   18268           5 :   CHECK_LT(final_size, initial_size + 1);
   18269             : }
   18270             : 
   18271       25880 : TEST(TestMemorySavingsMode) {
   18272           5 :   LocalContext context;
   18273           5 :   v8::Isolate* isolate = context->GetIsolate();
   18274          15 :   v8::internal::Isolate* i_isolate =
   18275             :       reinterpret_cast<v8::internal::Isolate*>(isolate);
   18276           5 :   CHECK(!i_isolate->IsMemorySavingsModeActive());
   18277           5 :   isolate->EnableMemorySavingsMode();
   18278           5 :   CHECK(i_isolate->IsMemorySavingsModeActive());
   18279           5 :   isolate->DisableMemorySavingsMode();
   18280           5 :   CHECK(!i_isolate->IsMemorySavingsModeActive());
   18281           5 : }
   18282             : 
   18283       25880 : TEST(Regress2333) {
   18284           5 :   LocalContext env;
   18285          20 :   for (int i = 0; i < 3; i++) {
   18286          15 :     CcTest::CollectGarbage(i::NEW_SPACE);
   18287           5 :   }
   18288           5 : }
   18289             : 
   18290             : static uint32_t* stack_limit;
   18291             : 
   18292          10 : static void GetStackLimitCallback(
   18293             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18294             :   stack_limit = reinterpret_cast<uint32_t*>(
   18295          10 :       CcTest::i_isolate()->stack_guard()->real_climit());
   18296          10 : }
   18297             : 
   18298             : 
   18299             : // Uses the address of a local variable to determine the stack top now.
   18300             : // Given a size, returns an address that is that far from the current
   18301             : // top of stack.
   18302             : static uint32_t* ComputeStackLimit(uint32_t size) {
   18303             :   uint32_t* answer = &size - (size / sizeof(size));
   18304             :   // If the size is very large and the stack is very near the bottom of
   18305             :   // memory then the calculation above may wrap around and give an address
   18306             :   // that is above the (downwards-growing) stack.  In that case we return
   18307             :   // a very low address.
   18308             :   if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
   18309             :   return answer;
   18310             : }
   18311             : 
   18312             : 
   18313             : // We need at least 165kB for an x64 debug build with clang and ASAN.
   18314             : static const int stack_breathing_room = 256 * i::KB;
   18315             : 
   18316             : 
   18317       25880 : TEST(SetStackLimit) {
   18318             :   uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
   18319             : 
   18320             :   // Set stack limit.
   18321           5 :   CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18322             : 
   18323             :   // Execute a script.
   18324           5 :   LocalContext env;
   18325          10 :   v8::HandleScope scope(env->GetIsolate());
   18326             :   Local<v8::FunctionTemplate> fun_templ =
   18327           5 :       v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
   18328          10 :   Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18329          25 :   CHECK(env->Global()
   18330             :             ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18331             :             .FromJust());
   18332             :   CompileRun("get_stack_limit();");
   18333             : 
   18334          10 :   CHECK(stack_limit == set_limit);
   18335           5 : }
   18336             : 
   18337             : 
   18338       25880 : TEST(SetStackLimitInThread) {
   18339             :   uint32_t* set_limit;
   18340             :   {
   18341           5 :     v8::Locker locker(CcTest::isolate());
   18342             :     set_limit = ComputeStackLimit(stack_breathing_room);
   18343             : 
   18344             :     // Set stack limit.
   18345           5 :     CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
   18346             : 
   18347             :     // Execute a script.
   18348          10 :     v8::HandleScope scope(CcTest::isolate());
   18349          10 :     LocalContext env;
   18350             :     Local<v8::FunctionTemplate> fun_templ =
   18351           5 :         v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
   18352          10 :     Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
   18353          25 :     CHECK(env->Global()
   18354             :               ->Set(env.local(), v8_str("get_stack_limit"), fun)
   18355             :               .FromJust());
   18356             :     CompileRun("get_stack_limit();");
   18357             : 
   18358          10 :     CHECK(stack_limit == set_limit);
   18359             :   }
   18360             :   {
   18361           5 :     v8::Locker locker(CcTest::isolate());
   18362           5 :     CHECK(stack_limit == set_limit);
   18363             :   }
   18364           5 : }
   18365             : 
   18366       25881 : THREADED_TEST(GetHeapStatistics) {
   18367           6 :   LocalContext c1;
   18368          12 :   v8::HandleScope scope(c1->GetIsolate());
   18369           6 :   v8::HeapStatistics heap_statistics;
   18370           6 :   CHECK_EQ(0u, heap_statistics.total_heap_size());
   18371           6 :   CHECK_EQ(0u, heap_statistics.used_heap_size());
   18372           6 :   c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
   18373           6 :   CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
   18374          12 :   CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
   18375           6 : }
   18376             : 
   18377       25880 : TEST(GetHeapSpaceStatistics) {
   18378           5 :   LocalContext c1;
   18379           5 :   v8::Isolate* isolate = c1->GetIsolate();
   18380          10 :   v8::HandleScope scope(isolate);
   18381           5 :   v8::HeapStatistics heap_statistics;
   18382             : 
   18383             :   // Force allocation in LO_SPACE so that every space has non-zero size.
   18384             :   v8::internal::Isolate* i_isolate =
   18385             :       reinterpret_cast<v8::internal::Isolate*>(isolate);
   18386           5 :   auto unused = i_isolate->factory()->TryNewFixedArray(512 * 1024, i::TENURED);
   18387             :   USE(unused);
   18388             : 
   18389           5 :   isolate->GetHeapStatistics(&heap_statistics);
   18390             : 
   18391             :   // Ensure that the sum of all the spaces matches the totals from
   18392             :   // GetHeapSpaceStatics.
   18393             :   size_t total_size = 0u;
   18394             :   size_t total_used_size = 0u;
   18395             :   size_t total_available_size = 0u;
   18396             :   size_t total_physical_size = 0u;
   18397          45 :   for (size_t i = 0; i < isolate->NumberOfHeapSpaces(); ++i) {
   18398          40 :     v8::HeapSpaceStatistics space_statistics;
   18399          40 :     isolate->GetHeapSpaceStatistics(&space_statistics, i);
   18400          40 :     CHECK_NOT_NULL(space_statistics.space_name());
   18401          40 :     total_size += space_statistics.space_size();
   18402          40 :     total_used_size += space_statistics.space_used_size();
   18403          40 :     total_available_size += space_statistics.space_available_size();
   18404          40 :     total_physical_size += space_statistics.physical_space_size();
   18405             :   }
   18406          10 :   total_available_size += CcTest::heap()->memory_allocator()->Available();
   18407             : 
   18408           5 :   CHECK_EQ(total_size, heap_statistics.total_heap_size());
   18409           5 :   CHECK_EQ(total_used_size, heap_statistics.used_heap_size());
   18410           5 :   CHECK_EQ(total_available_size, heap_statistics.total_available_size());
   18411          10 :   CHECK_EQ(total_physical_size, heap_statistics.total_physical_size());
   18412           5 : }
   18413             : 
   18414       25880 : TEST(NumberOfNativeContexts) {
   18415             :   static const size_t kNumTestContexts = 10;
   18416             :   i::Isolate* isolate = CcTest::i_isolate();
   18417             :   i::HandleScope scope(isolate);
   18418         110 :   v8::Global<v8::Context> context[kNumTestContexts];
   18419           5 :   v8::HeapStatistics heap_statistics;
   18420           5 :   CHECK_EQ(0u, heap_statistics.number_of_native_contexts());
   18421           5 :   CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18422           5 :   CHECK_EQ(0u, heap_statistics.number_of_native_contexts());
   18423          55 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18424             :     i::HandleScope inner(isolate);
   18425         100 :     context[i].Reset(CcTest::isolate(), v8::Context::New(CcTest::isolate()));
   18426          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18427          50 :     CHECK_EQ(i + 1, heap_statistics.number_of_native_contexts());
   18428             :   }
   18429          50 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18430          50 :     context[i].Reset();
   18431          50 :     CcTest::PreciseCollectAllGarbage();
   18432          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18433          50 :     CHECK_EQ(kNumTestContexts - i - 1u,
   18434             :              heap_statistics.number_of_native_contexts());
   18435             :   }
   18436           5 : }
   18437             : 
   18438       25880 : TEST(NumberOfDetachedContexts) {
   18439             :   static const size_t kNumTestContexts = 10;
   18440             :   i::Isolate* isolate = CcTest::i_isolate();
   18441             :   i::HandleScope scope(isolate);
   18442         110 :   v8::Global<v8::Context> context[kNumTestContexts];
   18443           5 :   v8::HeapStatistics heap_statistics;
   18444           5 :   CHECK_EQ(0u, heap_statistics.number_of_detached_contexts());
   18445           5 :   CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18446           5 :   CHECK_EQ(0u, heap_statistics.number_of_detached_contexts());
   18447          55 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18448             :     i::HandleScope inner(isolate);
   18449          50 :     v8::Local<v8::Context> local = v8::Context::New(CcTest::isolate());
   18450          50 :     context[i].Reset(CcTest::isolate(), local);
   18451          50 :     local->DetachGlobal();
   18452          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18453          50 :     CHECK_EQ(i + 1, heap_statistics.number_of_detached_contexts());
   18454             :   }
   18455          50 :   for (size_t i = 0; i < kNumTestContexts; i++) {
   18456          50 :     context[i].Reset();
   18457          50 :     CcTest::PreciseCollectAllGarbage();
   18458          50 :     CcTest::isolate()->GetHeapStatistics(&heap_statistics);
   18459          50 :     CHECK_EQ(kNumTestContexts - i - 1u,
   18460             :              heap_statistics.number_of_detached_contexts());
   18461             :   }
   18462           5 : }
   18463             : 
   18464             : class VisitorImpl : public v8::ExternalResourceVisitor {
   18465             :  public:
   18466           5 :   explicit VisitorImpl(TestResource** resource) {
   18467          20 :     for (int i = 0; i < 4; i++) {
   18468          20 :       resource_[i] = resource[i];
   18469          20 :       found_resource_[i] = false;
   18470             :     }
   18471             :   }
   18472           5 :   ~VisitorImpl() override = default;
   18473          25 :   void VisitExternalString(v8::Local<v8::String> string) override {
   18474          25 :     if (!string->IsExternal()) {
   18475           5 :       CHECK(string->IsExternalOneByte());
   18476          25 :       return;
   18477             :     }
   18478             :     v8::String::ExternalStringResource* resource =
   18479             :         string->GetExternalStringResource();
   18480          20 :     CHECK(resource);
   18481          80 :     for (int i = 0; i < 4; i++) {
   18482          80 :       if (resource_[i] == resource) {
   18483          20 :         CHECK(!found_resource_[i]);
   18484          20 :         found_resource_[i] = true;
   18485             :       }
   18486             :     }
   18487             :   }
   18488           5 :   void CheckVisitedResources() {
   18489          25 :     for (int i = 0; i < 4; i++) {
   18490          20 :       CHECK(found_resource_[i]);
   18491             :     }
   18492           5 :   }
   18493             : 
   18494             :  private:
   18495             :   v8::String::ExternalStringResource* resource_[4];
   18496             :   bool found_resource_[4];
   18497             : };
   18498             : 
   18499             : 
   18500       25880 : TEST(ExternalizeOldSpaceTwoByteCons) {
   18501           5 :   v8::Isolate* isolate = CcTest::isolate();
   18502           5 :   LocalContext env;
   18503          10 :   v8::HandleScope scope(isolate);
   18504             :   v8::Local<v8::String> cons =
   18505             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18506           5 :           ->ToString(env.local())
   18507           5 :           .ToLocalChecked();
   18508          10 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18509           5 :   CcTest::CollectAllAvailableGarbage();
   18510           5 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18511             : 
   18512             :   TestResource* resource = new TestResource(
   18513           5 :       AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
   18514           5 :   cons->MakeExternal(resource);
   18515             : 
   18516           5 :   CHECK(cons->IsExternal());
   18517           5 :   CHECK_EQ(resource, cons->GetExternalStringResource());
   18518             :   String::Encoding encoding;
   18519           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18520          10 :   CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
   18521           5 : }
   18522             : 
   18523             : 
   18524       25880 : TEST(ExternalizeOldSpaceOneByteCons) {
   18525           5 :   v8::Isolate* isolate = CcTest::isolate();
   18526           5 :   LocalContext env;
   18527          10 :   v8::HandleScope scope(isolate);
   18528             :   v8::Local<v8::String> cons =
   18529             :       CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
   18530           5 :           ->ToString(env.local())
   18531           5 :           .ToLocalChecked();
   18532          10 :   CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
   18533           5 :   CcTest::CollectAllAvailableGarbage();
   18534           5 :   CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
   18535             : 
   18536             :   TestOneByteResource* resource =
   18537           5 :       new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
   18538           5 :   cons->MakeExternal(resource);
   18539             : 
   18540           5 :   CHECK(cons->IsExternalOneByte());
   18541           5 :   CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
   18542             :   String::Encoding encoding;
   18543           5 :   CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
   18544          10 :   CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
   18545           5 : }
   18546             : 
   18547             : 
   18548       25880 : TEST(VisitExternalStrings) {
   18549           5 :   v8::Isolate* isolate = CcTest::isolate();
   18550           5 :   LocalContext env;
   18551          10 :   v8::HandleScope scope(isolate);
   18552             :   const char* string = "Some string";
   18553           5 :   uint16_t* two_byte_string = AsciiToTwoByteString(string);
   18554             :   TestResource* resource[4];
   18555          10 :   resource[0] = new TestResource(two_byte_string);
   18556             :   v8::Local<v8::String> string0 =
   18557           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
   18558           5 :           .ToLocalChecked();
   18559          10 :   resource[1] = new TestResource(two_byte_string, nullptr, false);
   18560             :   v8::Local<v8::String> string1 =
   18561           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
   18562           5 :           .ToLocalChecked();
   18563             : 
   18564             :   // Externalized symbol.
   18565          10 :   resource[2] = new TestResource(two_byte_string, nullptr, false);
   18566             :   v8::Local<v8::String> string2 =
   18567             :       v8::String::NewFromUtf8(env->GetIsolate(), string,
   18568           5 :                               v8::NewStringType::kInternalized)
   18569           5 :           .ToLocalChecked();
   18570           5 :   CHECK(string2->MakeExternal(resource[2]));
   18571             : 
   18572             :   // Symbolized External.
   18573          10 :   resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
   18574             :   v8::Local<v8::String> string3 =
   18575           5 :       v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
   18576           5 :           .ToLocalChecked();
   18577           5 :   CcTest::CollectAllAvailableGarbage();  // Tenure string.
   18578             :   // Turn into a symbol.
   18579             :   i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
   18580          10 :   CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
   18581             :       string3_i).is_null());
   18582          10 :   CHECK(string3_i->IsInternalizedString());
   18583             : 
   18584             :   // We need to add usages for string* to avoid warnings in GCC 4.7
   18585           5 :   CHECK(string0->IsExternal());
   18586           5 :   CHECK(string1->IsExternal());
   18587           5 :   CHECK(string2->IsExternal());
   18588           5 :   CHECK(string3->IsExternal());
   18589             : 
   18590             :   VisitorImpl visitor(resource);
   18591           5 :   isolate->VisitExternalResources(&visitor);
   18592          10 :   visitor.CheckVisitedResources();
   18593           5 : }
   18594             : 
   18595             : 
   18596       25880 : TEST(ExternalStringCollectedAtTearDown) {
   18597           5 :   int destroyed = 0;
   18598             :   v8::Isolate::CreateParams create_params;
   18599           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18600           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18601             :   { v8::Isolate::Scope isolate_scope(isolate);
   18602          10 :     v8::HandleScope handle_scope(isolate);
   18603             :     const char* s = "One string to test them all, one string to find them.";
   18604             :     TestOneByteResource* inscription =
   18605           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18606             :     v8::Local<v8::String> ring =
   18607           5 :         v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
   18608             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18609           5 :     CHECK_EQ(0, destroyed);
   18610             :     USE(ring);
   18611             :   }
   18612             : 
   18613           5 :   isolate->Dispose();
   18614             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18615           5 :   CHECK_EQ(1, destroyed);
   18616           5 : }
   18617             : 
   18618             : 
   18619       25880 : TEST(ExternalInternalizedStringCollectedAtTearDown) {
   18620           5 :   int destroyed = 0;
   18621             :   v8::Isolate::CreateParams create_params;
   18622           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   18623           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   18624             :   { v8::Isolate::Scope isolate_scope(isolate);
   18625           5 :     LocalContext env(isolate);
   18626          10 :     v8::HandleScope handle_scope(isolate);
   18627             :     CompileRun("var ring = 'One string to test them all';");
   18628             :     const char* s = "One string to test them all";
   18629             :     TestOneByteResource* inscription =
   18630           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18631             :     v8::Local<v8::String> ring =
   18632          10 :         CompileRun("ring")->ToString(env.local()).ToLocalChecked();
   18633          10 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18634           5 :     ring->MakeExternal(inscription);
   18635             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18636           5 :     CHECK_EQ(0, destroyed);
   18637             :     USE(ring);
   18638             :   }
   18639             : 
   18640           5 :   isolate->Dispose();
   18641             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18642           5 :   CHECK_EQ(1, destroyed);
   18643           5 : }
   18644             : 
   18645             : 
   18646       25880 : TEST(ExternalInternalizedStringCollectedAtGC) {
   18647           5 :   int destroyed = 0;
   18648           5 :   { LocalContext env;
   18649          10 :     v8::HandleScope handle_scope(env->GetIsolate());
   18650             :     CompileRun("var ring = 'One string to test them all';");
   18651             :     const char* s = "One string to test them all";
   18652             :     TestOneByteResource* inscription =
   18653           5 :         new TestOneByteResource(i::StrDup(s), &destroyed);
   18654             :     v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
   18655          10 :     CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
   18656           5 :     ring->MakeExternal(inscription);
   18657             :     // Ring is still alive.  Orcs are roaming freely across our lands.
   18658           5 :     CHECK_EQ(0, destroyed);
   18659           5 :     USE(ring);
   18660             :   }
   18661             : 
   18662             :   // Garbage collector deals swift blows to evil.
   18663           5 :   CcTest::i_isolate()->compilation_cache()->Clear();
   18664           5 :   CcTest::CollectAllAvailableGarbage();
   18665             : 
   18666             :   // Ring has been destroyed.  Free Peoples of Middle-earth Rejoice.
   18667           5 :   CHECK_EQ(1, destroyed);
   18668           5 : }
   18669             : 
   18670             : 
   18671             : static double DoubleFromBits(uint64_t value) {
   18672             :   double target;
   18673             :   i::MemCopy(&target, &value, sizeof(target));
   18674             :   return target;
   18675             : }
   18676             : 
   18677             : 
   18678             : static uint64_t DoubleToBits(double value) {
   18679             :   uint64_t target;
   18680             :   i::MemCopy(&target, &value, sizeof(target));
   18681             :   return target;
   18682             : }
   18683             : 
   18684             : 
   18685         120 : static double DoubleToDateTime(double input) {
   18686             :   double date_limit = 864e13;
   18687         120 :   if (std::isnan(input) || input < -date_limit || input > date_limit) {
   18688             :     return std::numeric_limits<double>::quiet_NaN();
   18689             :   }
   18690          60 :   return (input < 0) ? -(std::floor(-input)) : std::floor(input);
   18691             : }
   18692             : 
   18693             : 
   18694             : // We don't have a consistent way to write 64-bit constants syntactically, so we
   18695             : // split them into two 32-bit constants and combine them programmatically.
   18696             : static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
   18697             :   return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
   18698             : }
   18699             : 
   18700             : 
   18701       25881 : THREADED_TEST(QuietSignalingNaNs) {
   18702           6 :   LocalContext context;
   18703           6 :   v8::Isolate* isolate = context->GetIsolate();
   18704          12 :   v8::HandleScope scope(isolate);
   18705          12 :   v8::TryCatch try_catch(isolate);
   18706             : 
   18707             :   // Special double values.
   18708             :   double snan = DoubleFromBits(0x7FF00000, 0x00000001);
   18709             :   double qnan = DoubleFromBits(0x7FF80000, 0x00000000);
   18710             :   double infinity = DoubleFromBits(0x7FF00000, 0x00000000);
   18711             :   double max_normal = DoubleFromBits(0x7FEFFFFF, 0xFFFFFFFFu);
   18712             :   double min_normal = DoubleFromBits(0x00100000, 0x00000000);
   18713             :   double max_denormal = DoubleFromBits(0x000FFFFF, 0xFFFFFFFFu);
   18714             :   double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
   18715             : 
   18716             :   // Date values are capped at +/-100000000 days (times 864e5 ms per day)
   18717             :   // on either side of the epoch.
   18718             :   double date_limit = 864e13;
   18719             : 
   18720             :   double test_values[] = {
   18721             :       snan,
   18722             :       qnan,
   18723             :       infinity,
   18724             :       max_normal,
   18725             :       date_limit + 1,
   18726             :       date_limit,
   18727             :       min_normal,
   18728             :       max_denormal,
   18729             :       min_denormal,
   18730             :       0,
   18731             :       -0,
   18732             :       -min_denormal,
   18733             :       -max_denormal,
   18734             :       -min_normal,
   18735             :       -date_limit,
   18736             :       -date_limit - 1,
   18737             :       -max_normal,
   18738             :       -infinity,
   18739             :       -qnan,
   18740             :       -snan
   18741           6 :   };
   18742             :   int num_test_values = 20;
   18743             : 
   18744         126 :   for (int i = 0; i < num_test_values; i++) {
   18745         120 :     double test_value = test_values[i];
   18746             : 
   18747             :     // Check that Number::New preserves non-NaNs and quiets SNaNs.
   18748         120 :     v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
   18749         240 :     double stored_number = number->NumberValue(context.local()).FromJust();
   18750         120 :     if (!std::isnan(test_value)) {
   18751          96 :       CHECK_EQ(test_value, stored_number);
   18752             :     } else {
   18753             :       uint64_t stored_bits = DoubleToBits(stored_number);
   18754             :       // Check if quiet nan (bits 51..62 all set).
   18755             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18756             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   18757             :     !defined(USE_SIMULATOR)
   18758             :       // Most significant fraction bit for quiet nan is set to 0
   18759             :       // on MIPS architecture. Allowed by IEEE-754.
   18760             :       CHECK_EQ(0xFFE, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18761             : #else
   18762          24 :       CHECK_EQ(0xFFF, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18763             : #endif
   18764             :     }
   18765             : 
   18766             :     // Check that Date::New preserves non-NaNs in the date range and
   18767             :     // quiets SNaNs.
   18768             :     v8::Local<v8::Value> date =
   18769         120 :         v8::Date::New(context.local(), test_value).ToLocalChecked();
   18770         120 :     double expected_stored_date = DoubleToDateTime(test_value);
   18771         240 :     double stored_date = date->NumberValue(context.local()).FromJust();
   18772         120 :     if (!std::isnan(expected_stored_date)) {
   18773          60 :       CHECK_EQ(expected_stored_date, stored_date);
   18774             :     } else {
   18775             :       uint64_t stored_bits = DoubleToBits(stored_date);
   18776             :       // Check if quiet nan (bits 51..62 all set).
   18777             : #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
   18778             :     !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) &&   \
   18779             :     !defined(USE_SIMULATOR)
   18780             :       // Most significant fraction bit for quiet nan is set to 0
   18781             :       // on MIPS architecture. Allowed by IEEE-754.
   18782             :       CHECK_EQ(0xFFE, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18783             : #else
   18784          60 :       CHECK_EQ(0xFFF, static_cast<int>((stored_bits >> 51) & 0xFFF));
   18785             : #endif
   18786             :     }
   18787           6 :   }
   18788           6 : }
   18789             : 
   18790             : 
   18791          66 : static void SpaghettiIncident(
   18792         198 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   18793          66 :   v8::HandleScope scope(args.GetIsolate());
   18794         132 :   v8::TryCatch tc(args.GetIsolate());
   18795             :   v8::MaybeLocal<v8::String> str(
   18796         132 :       args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
   18797             :   USE(str);
   18798          66 :   if (tc.HasCaught())
   18799         132 :     tc.ReThrow();
   18800          66 : }
   18801             : 
   18802             : 
   18803             : // Test that an exception can be propagated down through a spaghetti
   18804             : // stack using ReThrow.
   18805       25881 : THREADED_TEST(SpaghettiStackReThrow) {
   18806           6 :   v8::Isolate* isolate = CcTest::isolate();
   18807           6 :   v8::HandleScope scope(isolate);
   18808          12 :   LocalContext context;
   18809             :   context->Global()
   18810             :       ->Set(context.local(), v8_str("s"),
   18811           6 :             v8::FunctionTemplate::New(isolate, SpaghettiIncident)
   18812          18 :                 ->GetFunction(context.local())
   18813          30 :                 .ToLocalChecked())
   18814          12 :       .FromJust();
   18815          12 :   v8::TryCatch try_catch(isolate);
   18816             :   CompileRun(
   18817             :       "var i = 0;"
   18818             :       "var o = {"
   18819             :       "  toString: function () {"
   18820             :       "    if (i == 10) {"
   18821             :       "      throw 'Hey!';"
   18822             :       "    } else {"
   18823             :       "      i++;"
   18824             :       "      return s(o);"
   18825             :       "    }"
   18826             :       "  }"
   18827             :       "};"
   18828             :       "s(o);");
   18829           6 :   CHECK(try_catch.HasCaught());
   18830          12 :   v8::String::Utf8Value value(isolate, try_catch.Exception());
   18831          12 :   CHECK_EQ(0, strcmp(*value, "Hey!"));
   18832           6 : }
   18833             : 
   18834             : 
   18835       25880 : TEST(Regress528) {
   18836             :   ManualGCScope manual_gc_scope;
   18837           5 :   v8::V8::Initialize();
   18838           5 :   v8::Isolate* isolate = CcTest::isolate();
   18839           5 :   i::FLAG_retain_maps_for_n_gc = 0;
   18840          10 :   v8::HandleScope scope(isolate);
   18841             :   v8::Local<Context> other_context;
   18842             :   int gc_count;
   18843             : 
   18844             :   // Create a context used to keep the code from aging in the compilation
   18845             :   // cache.
   18846           5 :   other_context = Context::New(isolate);
   18847             : 
   18848             :   // Context-dependent context data creates reference from the compilation
   18849             :   // cache to the global object.
   18850             :   const char* source_simple = "1";
   18851             :   {
   18852           5 :     v8::HandleScope scope(isolate);
   18853           5 :     v8::Local<Context> context = Context::New(isolate);
   18854             : 
   18855           5 :     context->Enter();
   18856           5 :     Local<v8::String> obj = v8_str("");
   18857           5 :     context->SetEmbedderData(0, obj);
   18858             :     CompileRun(source_simple);
   18859           5 :     context->Exit();
   18860             :   }
   18861           5 :   isolate->ContextDisposedNotification();
   18862           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   18863           5 :     other_context->Enter();
   18864             :     CompileRun(source_simple);
   18865           5 :     other_context->Exit();
   18866           5 :     CcTest::CollectAllGarbage();
   18867           5 :     if (GetGlobalObjectsCount() == 1) break;
   18868             :   }
   18869           5 :   CHECK_GE(2, gc_count);
   18870           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   18871             : 
   18872             :   // Eval in a function creates reference from the compilation cache to the
   18873             :   // global object.
   18874             :   const char* source_eval = "function f(){eval('1')}; f()";
   18875             :   {
   18876           5 :     v8::HandleScope scope(isolate);
   18877           5 :     v8::Local<Context> context = Context::New(isolate);
   18878             : 
   18879           5 :     context->Enter();
   18880             :     CompileRun(source_eval);
   18881           5 :     context->Exit();
   18882             :   }
   18883           5 :   isolate->ContextDisposedNotification();
   18884           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   18885           5 :     other_context->Enter();
   18886             :     CompileRun(source_eval);
   18887           5 :     other_context->Exit();
   18888           5 :     CcTest::CollectAllGarbage();
   18889           5 :     if (GetGlobalObjectsCount() == 1) break;
   18890             :   }
   18891           5 :   CHECK_GE(2, gc_count);
   18892           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   18893             : 
   18894             :   // Looking up the line number for an exception creates reference from the
   18895             :   // compilation cache to the global object.
   18896             :   const char* source_exception = "function f(){throw 1;} f()";
   18897             :   {
   18898           5 :     v8::HandleScope scope(isolate);
   18899           5 :     v8::Local<Context> context = Context::New(isolate);
   18900             : 
   18901           5 :     context->Enter();
   18902          10 :     v8::TryCatch try_catch(isolate);
   18903             :     CompileRun(source_exception);
   18904           5 :     CHECK(try_catch.HasCaught());
   18905           5 :     v8::Local<v8::Message> message = try_catch.Message();
   18906           5 :     CHECK(!message.IsEmpty());
   18907          10 :     CHECK_EQ(1, message->GetLineNumber(context).FromJust());
   18908          10 :     context->Exit();
   18909             :   }
   18910           5 :   isolate->ContextDisposedNotification();
   18911           5 :   for (gc_count = 1; gc_count < 10; gc_count++) {
   18912           5 :     other_context->Enter();
   18913             :     CompileRun(source_exception);
   18914           5 :     other_context->Exit();
   18915           5 :     CcTest::CollectAllGarbage();
   18916           5 :     if (GetGlobalObjectsCount() == 1) break;
   18917             :   }
   18918           5 :   CHECK_GE(2, gc_count);
   18919           5 :   CHECK_EQ(1, GetGlobalObjectsCount());
   18920             : 
   18921           5 :   isolate->ContextDisposedNotification();
   18922           5 : }
   18923             : 
   18924             : 
   18925       25881 : THREADED_TEST(ScriptOrigin) {
   18926           6 :   LocalContext env;
   18927           6 :   v8::Isolate* isolate = env->GetIsolate();
   18928          12 :   v8::HandleScope scope(isolate);
   18929           6 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 1));
   18930           6 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   18931           6 :   array->Set(isolate, 0, symbol);
   18932             : 
   18933             :   v8::ScriptOrigin origin = v8::ScriptOrigin(
   18934             :       v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
   18935             :       v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
   18936             :       v8::Local<v8::Integer>(), v8_str("http://sourceMapUrl"),
   18937             :       v8::True(env->GetIsolate()), v8::False(env->GetIsolate()),
   18938          42 :       v8::False(env->GetIsolate()), array);
   18939           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   18940           6 :   v8::Script::Compile(env.local(), script, &origin)
   18941           6 :       .ToLocalChecked()
   18942           6 :       ->Run(env.local())
   18943           6 :       .ToLocalChecked();
   18944             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18945          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18946             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   18947          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   18948             : 
   18949           6 :   v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
   18950           6 :   CHECK_EQ(0, strcmp("test",
   18951             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18952             :                                             script_origin_f.ResourceName())));
   18953          12 :   CHECK_EQ(
   18954             :       1,
   18955             :       script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   18956           6 :   CHECK(script_origin_f.Options().IsSharedCrossOrigin());
   18957           6 :   CHECK(script_origin_f.Options().IsOpaque());
   18958           6 :   printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
   18959          12 :   CHECK(script_origin_f.HostDefinedOptions()->Get(isolate, 0)->IsSymbol());
   18960             : 
   18961           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   18962             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18963             :                                             script_origin_f.SourceMapUrl())));
   18964             : 
   18965           6 :   v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
   18966           6 :   CHECK_EQ(0, strcmp("test",
   18967             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18968             :                                             script_origin_g.ResourceName())));
   18969          12 :   CHECK_EQ(
   18970             :       1,
   18971             :       script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
   18972           6 :   CHECK(script_origin_g.Options().IsSharedCrossOrigin());
   18973           6 :   CHECK(script_origin_g.Options().IsOpaque());
   18974           6 :   CHECK_EQ(0, strcmp("http://sourceMapUrl",
   18975             :                      *v8::String::Utf8Value(env->GetIsolate(),
   18976             :                                             script_origin_g.SourceMapUrl())));
   18977          18 :   CHECK(script_origin_g.HostDefinedOptions()->Get(isolate, 0)->IsSymbol());
   18978           6 : }
   18979             : 
   18980             : 
   18981       25881 : THREADED_TEST(FunctionGetInferredName) {
   18982           6 :   LocalContext env;
   18983          12 :   v8::HandleScope scope(env->GetIsolate());
   18984           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   18985             :   v8::Local<v8::String> script =
   18986           6 :       v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
   18987           6 :   v8::Script::Compile(env.local(), script, &origin)
   18988           6 :       .ToLocalChecked()
   18989           6 :       ->Run(env.local())
   18990           6 :       .ToLocalChecked();
   18991             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   18992          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   18993          12 :   CHECK_EQ(0,
   18994             :            strcmp("foo.bar.baz", *v8::String::Utf8Value(env->GetIsolate(),
   18995           6 :                                                         f->GetInferredName())));
   18996           6 : }
   18997             : 
   18998             : 
   18999       25881 : THREADED_TEST(FunctionGetDebugName) {
   19000           6 :   LocalContext env;
   19001           6 :   v8::Isolate* isolate = env->GetIsolate();
   19002          12 :   v8::HandleScope scope(isolate);
   19003             :   const char* code =
   19004             :       "var error = false;"
   19005             :       "function a() { this.x = 1; };"
   19006             :       "a.displayName = 'display_a';"
   19007             :       "var b = (function() {"
   19008             :       "  var f = function() { this.x = 2; };"
   19009             :       "  f.displayName = 'display_b';"
   19010             :       "  return f;"
   19011             :       "})();"
   19012             :       "var c = function() {};"
   19013             :       "c.__defineGetter__('displayName', function() {"
   19014             :       "  error = true;"
   19015             :       "  throw new Error();"
   19016             :       "});"
   19017             :       "function d() {};"
   19018             :       "d.__defineGetter__('displayName', function() {"
   19019             :       "  error = true;"
   19020             :       "  return 'wrong_display_name';"
   19021             :       "});"
   19022             :       "function e() {};"
   19023             :       "e.displayName = 'wrong_display_name';"
   19024             :       "e.__defineSetter__('displayName', function() {"
   19025             :       "  error = true;"
   19026             :       "  throw new Error();"
   19027             :       "});"
   19028             :       "function f() {};"
   19029             :       "f.displayName = { 'foo': 6, toString: function() {"
   19030             :       "  error = true;"
   19031             :       "  return 'wrong_display_name';"
   19032             :       "}};"
   19033             :       "var g = function() {"
   19034             :       "  arguments.callee.displayName = 'set_in_runtime';"
   19035             :       "}; g();"
   19036             :       "var h = function() {};"
   19037             :       "h.displayName = 'displayName';"
   19038             :       "Object.defineProperty(h, 'name', { value: 'function.name' });"
   19039             :       "var i = function() {};"
   19040             :       "i.displayName = 239;"
   19041             :       "Object.defineProperty(i, 'name', { value: 'function.name' });"
   19042             :       "var j = function() {};"
   19043             :       "Object.defineProperty(j, 'name', { value: 'function.name' });"
   19044             :       "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
   19045             :       "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
   19046           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19047           6 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19048           6 :       .ToLocalChecked()
   19049           6 :       ->Run(env.local())
   19050           6 :       .ToLocalChecked();
   19051             :   v8::Local<v8::Value> error =
   19052          30 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19053           6 :   CHECK(!error->BooleanValue(isolate));
   19054             :   const char* functions[] = {"a", "display_a",
   19055             :                              "b", "display_b",
   19056             :                              "c", "c",
   19057             :                              "d", "d",
   19058             :                              "e", "e",
   19059             :                              "f", "f",
   19060             :                              "g", "set_in_runtime",
   19061             :                              "h", "displayName",
   19062             :                              "i", "function.name",
   19063             :                              "j", "function.name",
   19064             :                              "k", "foo.bar.baz",
   19065           6 :                              "l", "baz"};
   19066          78 :   for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
   19067             :     v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19068             :         env->Global()
   19069             :             ->Get(env.local(),
   19070          72 :                   v8::String::NewFromUtf8(isolate, functions[i * 2],
   19071          72 :                                           v8::NewStringType::kNormal)
   19072         288 :                       .ToLocalChecked())
   19073          72 :             .ToLocalChecked());
   19074          72 :     CHECK_EQ(0, strcmp(functions[i * 2 + 1],
   19075             :                        *v8::String::Utf8Value(isolate, f->GetDebugName())));
   19076           6 :   }
   19077           6 : }
   19078             : 
   19079             : 
   19080       25881 : THREADED_TEST(FunctionGetDisplayName) {
   19081           6 :   LocalContext env;
   19082           6 :   v8::Isolate* isolate = env->GetIsolate();
   19083          12 :   v8::HandleScope scope(isolate);
   19084             :   const char* code = "var error = false;"
   19085             :                      "function a() { this.x = 1; };"
   19086             :                      "a.displayName = 'display_a';"
   19087             :                      "var b = (function() {"
   19088             :                      "  var f = function() { this.x = 2; };"
   19089             :                      "  f.displayName = 'display_b';"
   19090             :                      "  return f;"
   19091             :                      "})();"
   19092             :                      "var c = function() {};"
   19093             :                      "c.__defineGetter__('displayName', function() {"
   19094             :                      "  error = true;"
   19095             :                      "  throw new Error();"
   19096             :                      "});"
   19097             :                      "function d() {};"
   19098             :                      "d.__defineGetter__('displayName', function() {"
   19099             :                      "  error = true;"
   19100             :                      "  return 'wrong_display_name';"
   19101             :                      "});"
   19102             :                      "function e() {};"
   19103             :                      "e.displayName = 'wrong_display_name';"
   19104             :                      "e.__defineSetter__('displayName', function() {"
   19105             :                      "  error = true;"
   19106             :                      "  throw new Error();"
   19107             :                      "});"
   19108             :                      "function f() {};"
   19109             :                      "f.displayName = { 'foo': 6, toString: function() {"
   19110             :                      "  error = true;"
   19111             :                      "  return 'wrong_display_name';"
   19112             :                      "}};"
   19113             :                      "var g = function() {"
   19114             :                      "  arguments.callee.displayName = 'set_in_runtime';"
   19115             :                      "}; g();";
   19116           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19117           6 :   v8::Script::Compile(env.local(), v8_str(code), &origin)
   19118           6 :       .ToLocalChecked()
   19119           6 :       ->Run(env.local())
   19120           6 :       .ToLocalChecked();
   19121             :   v8::Local<v8::Value> error =
   19122          30 :       env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
   19123             :   v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
   19124          30 :       env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
   19125             :   v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
   19126          30 :       env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
   19127             :   v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
   19128          30 :       env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
   19129             :   v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
   19130          30 :       env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
   19131             :   v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
   19132          30 :       env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
   19133             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19134          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19135             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19136          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19137           6 :   CHECK(!error->BooleanValue(isolate));
   19138           6 :   CHECK_EQ(0, strcmp("display_a",
   19139             :                      *v8::String::Utf8Value(isolate, a->GetDisplayName())));
   19140           6 :   CHECK_EQ(0, strcmp("display_b",
   19141             :                      *v8::String::Utf8Value(isolate, b->GetDisplayName())));
   19142          12 :   CHECK(c->GetDisplayName()->IsUndefined());
   19143          12 :   CHECK(d->GetDisplayName()->IsUndefined());
   19144          12 :   CHECK(e->GetDisplayName()->IsUndefined());
   19145          12 :   CHECK(f->GetDisplayName()->IsUndefined());
   19146           6 :   CHECK_EQ(0, strcmp("set_in_runtime",
   19147           6 :                      *v8::String::Utf8Value(isolate, g->GetDisplayName())));
   19148           6 : }
   19149             : 
   19150             : 
   19151       25881 : THREADED_TEST(ScriptLineNumber) {
   19152           6 :   LocalContext env;
   19153          12 :   v8::HandleScope scope(env->GetIsolate());
   19154           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19155           6 :   v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
   19156           6 :   v8::Script::Compile(env.local(), script, &origin)
   19157           6 :       .ToLocalChecked()
   19158           6 :       ->Run(env.local())
   19159           6 :       .ToLocalChecked();
   19160             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19161          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19162             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19163          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19164           6 :   CHECK_EQ(0, f->GetScriptLineNumber());
   19165          12 :   CHECK_EQ(2, g->GetScriptLineNumber());
   19166           6 : }
   19167             : 
   19168             : 
   19169       25881 : THREADED_TEST(ScriptColumnNumber) {
   19170           6 :   LocalContext env;
   19171           6 :   v8::Isolate* isolate = env->GetIsolate();
   19172          12 :   v8::HandleScope scope(isolate);
   19173             :   v8::ScriptOrigin origin =
   19174             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19175           6 :                        v8::Integer::New(isolate, 2));
   19176             :   v8::Local<v8::String> script =
   19177           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19178           6 :   v8::Script::Compile(env.local(), script, &origin)
   19179           6 :       .ToLocalChecked()
   19180           6 :       ->Run(env.local())
   19181           6 :       .ToLocalChecked();
   19182             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19183          30 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19184             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19185          30 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19186           6 :   CHECK_EQ(14, foo->GetScriptColumnNumber());
   19187          12 :   CHECK_EQ(17, bar->GetScriptColumnNumber());
   19188           6 : }
   19189             : 
   19190             : 
   19191       25881 : THREADED_TEST(FunctionGetScriptId) {
   19192           6 :   LocalContext env;
   19193           6 :   v8::Isolate* isolate = env->GetIsolate();
   19194          12 :   v8::HandleScope scope(isolate);
   19195             :   v8::ScriptOrigin origin =
   19196             :       v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
   19197           6 :                        v8::Integer::New(isolate, 2));
   19198             :   v8::Local<v8::String> scriptSource =
   19199           6 :       v8_str("function foo() {}\n\n     function bar() {}");
   19200             :   v8::Local<v8::Script> script(
   19201           6 :       v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
   19202           6 :   script->Run(env.local()).ToLocalChecked();
   19203             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   19204          30 :       env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
   19205             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
   19206          30 :       env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
   19207          12 :   CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
   19208          18 :   CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
   19209           6 : }
   19210             : 
   19211             : 
   19212       25881 : THREADED_TEST(FunctionGetBoundFunction) {
   19213           6 :   LocalContext env;
   19214          12 :   v8::HandleScope scope(env->GetIsolate());
   19215           6 :   v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
   19216             :   v8::Local<v8::String> script = v8_str(
   19217             :       "var a = new Object();\n"
   19218             :       "a.x = 1;\n"
   19219             :       "function f () { return this.x };\n"
   19220             :       "var g = f.bind(a);\n"
   19221           6 :       "var b = g();");
   19222           6 :   v8::Script::Compile(env.local(), script, &origin)
   19223           6 :       .ToLocalChecked()
   19224           6 :       ->Run(env.local())
   19225           6 :       .ToLocalChecked();
   19226             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
   19227          30 :       env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
   19228             :   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
   19229          30 :       env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
   19230          12 :   CHECK(g->GetBoundFunction()->IsFunction());
   19231             :   Local<v8::Function> original_function = Local<v8::Function>::Cast(
   19232           6 :       g->GetBoundFunction());
   19233          18 :   CHECK(f->GetName()
   19234             :             ->Equals(env.local(), original_function->GetName())
   19235             :             .FromJust());
   19236           6 :   CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
   19237           6 :   CHECK_EQ(f->GetScriptColumnNumber(),
   19238           6 :            original_function->GetScriptColumnNumber());
   19239           6 : }
   19240             : 
   19241             : 
   19242         330 : static void GetterWhichReturns42(
   19243             :     Local<String> name,
   19244             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19245         660 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19246         660 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19247         330 :   info.GetReturnValue().Set(v8_num(42));
   19248         330 : }
   19249             : 
   19250             : 
   19251         270 : static void SetterWhichSetsYOnThisTo23(
   19252             :     Local<String> name,
   19253             :     Local<Value> value,
   19254             :     const v8::PropertyCallbackInfo<void>& info) {
   19255         540 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19256         540 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19257             :   Local<Object>::Cast(info.This())
   19258         810 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19259         540 :       .FromJust();
   19260         270 : }
   19261             : 
   19262             : 
   19263         120 : void FooGetInterceptor(Local<Name> name,
   19264             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19265         240 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19266         240 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19267         360 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19268         240 :            .FromJust()) {
   19269         120 :     return;
   19270             :   }
   19271          96 :   info.GetReturnValue().Set(v8_num(42));
   19272             : }
   19273             : 
   19274             : 
   19275         336 : void FooSetInterceptor(Local<Name> name, Local<Value> value,
   19276             :                        const v8::PropertyCallbackInfo<v8::Value>& info) {
   19277         672 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
   19278         672 :   CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
   19279        1008 :   if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   19280         672 :            .FromJust()) {
   19281         336 :     return;
   19282             :   }
   19283             :   Local<Object>::Cast(info.This())
   19284         288 :       ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19285         192 :       .FromJust();
   19286          96 :   info.GetReturnValue().Set(v8_num(23));
   19287             : }
   19288             : 
   19289             : 
   19290       25880 : TEST(SetterOnConstructorPrototype) {
   19291           5 :   v8::Isolate* isolate = CcTest::isolate();
   19292           5 :   v8::HandleScope scope(isolate);
   19293           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19294             :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19295           5 :                      SetterWhichSetsYOnThisTo23);
   19296          10 :   LocalContext context;
   19297          30 :   CHECK(context->Global()
   19298             :             ->Set(context.local(), v8_str("P"),
   19299             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19300             :             .FromJust());
   19301             :   CompileRun("function C1() {"
   19302             :              "  this.x = 23;"
   19303             :              "};"
   19304             :              "C1.prototype = P;"
   19305             :              "function C2() {"
   19306             :              "  this.x = 23"
   19307             :              "};"
   19308             :              "C2.prototype = { };"
   19309             :              "C2.prototype.__proto__ = P;");
   19310             : 
   19311             :   v8::Local<v8::Script> script;
   19312             :   script = v8_compile("new C1();");
   19313          55 :   for (int i = 0; i < 10; i++) {
   19314             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19315          50 :         script->Run(context.local()).ToLocalChecked());
   19316         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19317             :                      .ToLocalChecked()
   19318             :                      ->Int32Value(context.local())
   19319             :                      .FromJust());
   19320         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19321             :                      .ToLocalChecked()
   19322             :                      ->Int32Value(context.local())
   19323             :                      .FromJust());
   19324             :   }
   19325             : 
   19326             :   script = v8_compile("new C2();");
   19327          55 :   for (int i = 0; i < 10; i++) {
   19328             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19329          50 :         script->Run(context.local()).ToLocalChecked());
   19330         200 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
   19331             :                      .ToLocalChecked()
   19332             :                      ->Int32Value(context.local())
   19333             :                      .FromJust());
   19334         200 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
   19335             :                      .ToLocalChecked()
   19336             :                      ->Int32Value(context.local())
   19337             :                      .FromJust());
   19338           5 :   }
   19339           5 : }
   19340             : 
   19341             : 
   19342           0 : static void NamedPropertySetterWhichSetsYOnThisTo23(
   19343             :     Local<Name> name, Local<Value> value,
   19344             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   19345           0 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
   19346           0 :           .FromJust()) {
   19347             :     Local<Object>::Cast(info.This())
   19348           0 :         ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
   19349           0 :         .FromJust();
   19350             :   }
   19351           0 : }
   19352             : 
   19353             : 
   19354       25881 : THREADED_TEST(InterceptorOnConstructorPrototype) {
   19355           6 :   v8::Isolate* isolate = CcTest::isolate();
   19356           6 :   v8::HandleScope scope(isolate);
   19357           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19358             :   templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   19359             :       NamedPropertyGetterWhichReturns42,
   19360           6 :       NamedPropertySetterWhichSetsYOnThisTo23));
   19361          12 :   LocalContext context;
   19362          36 :   CHECK(context->Global()
   19363             :             ->Set(context.local(), v8_str("P"),
   19364             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19365             :             .FromJust());
   19366             :   CompileRun("function C1() {"
   19367             :              "  this.x = 23;"
   19368             :              "};"
   19369             :              "C1.prototype = P;"
   19370             :              "function C2() {"
   19371             :              "  this.x = 23"
   19372             :              "};"
   19373             :              "C2.prototype = { };"
   19374             :              "C2.prototype.__proto__ = P;");
   19375             : 
   19376             :   v8::Local<v8::Script> script;
   19377             :   script = v8_compile("new C1();");
   19378          66 :   for (int i = 0; i < 10; i++) {
   19379             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19380          60 :         script->Run(context.local()).ToLocalChecked());
   19381         240 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   19382             :                      .ToLocalChecked()
   19383             :                      ->Int32Value(context.local())
   19384             :                      .FromJust());
   19385         240 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   19386             :                      .ToLocalChecked()
   19387             :                      ->Int32Value(context.local())
   19388             :                      .FromJust());
   19389             :   }
   19390             : 
   19391             :   script = v8_compile("new C2();");
   19392          66 :   for (int i = 0; i < 10; i++) {
   19393             :     v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
   19394          60 :         script->Run(context.local()).ToLocalChecked());
   19395         240 :     CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
   19396             :                      .ToLocalChecked()
   19397             :                      ->Int32Value(context.local())
   19398             :                      .FromJust());
   19399         240 :     CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
   19400             :                      .ToLocalChecked()
   19401             :                      ->Int32Value(context.local())
   19402             :                      .FromJust());
   19403           6 :   }
   19404           6 : }
   19405             : 
   19406             : 
   19407       25880 : TEST(Regress618) {
   19408             :   const char* source = "function C1() {"
   19409             :                        "  this.x = 23;"
   19410             :                        "};"
   19411             :                        "C1.prototype = P;";
   19412             : 
   19413           5 :   LocalContext context;
   19414           5 :   v8::Isolate* isolate = context->GetIsolate();
   19415          10 :   v8::HandleScope scope(isolate);
   19416             :   v8::Local<v8::Script> script;
   19417             : 
   19418             :   // Use a simple object as prototype.
   19419           5 :   v8::Local<v8::Object> prototype = v8::Object::New(isolate);
   19420          20 :   prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
   19421          25 :   CHECK(context->Global()
   19422             :             ->Set(context.local(), v8_str("P"), prototype)
   19423             :             .FromJust());
   19424             : 
   19425             :   // This compile will add the code to the compilation cache.
   19426             :   CompileRun(source);
   19427             : 
   19428             :   script = v8_compile("new C1();");
   19429             :   // Allow enough iterations for the inobject slack tracking logic
   19430             :   // to finalize instance size and install the fast construct stub.
   19431        1285 :   for (int i = 0; i < 256; i++) {
   19432             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19433        1280 :         script->Run(context.local()).ToLocalChecked());
   19434        5120 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
   19435             :                      .ToLocalChecked()
   19436             :                      ->Int32Value(context.local())
   19437             :                      .FromJust());
   19438        5120 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
   19439             :                      .ToLocalChecked()
   19440             :                      ->Int32Value(context.local())
   19441             :                      .FromJust());
   19442             :   }
   19443             : 
   19444             :   // Use an API object with accessors as prototype.
   19445           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   19446             :   templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
   19447           5 :                      SetterWhichSetsYOnThisTo23);
   19448          30 :   CHECK(context->Global()
   19449             :             ->Set(context.local(), v8_str("P"),
   19450             :                   templ->NewInstance(context.local()).ToLocalChecked())
   19451             :             .FromJust());
   19452             : 
   19453             :   // This compile will get the code from the compilation cache.
   19454             :   CompileRun(source);
   19455             : 
   19456             :   script = v8_compile("new C1();");
   19457          55 :   for (int i = 0; i < 10; i++) {
   19458             :     v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
   19459          50 :         script->Run(context.local()).ToLocalChecked());
   19460         200 :     CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
   19461             :                      .ToLocalChecked()
   19462             :                      ->Int32Value(context.local())
   19463             :                      .FromJust());
   19464         200 :     CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
   19465             :                      .ToLocalChecked()
   19466             :                      ->Int32Value(context.local())
   19467             :                      .FromJust());
   19468           5 :   }
   19469           5 : }
   19470             : 
   19471             : v8::Isolate* gc_callbacks_isolate = nullptr;
   19472             : int prologue_call_count = 0;
   19473             : int epilogue_call_count = 0;
   19474             : int prologue_call_count_second = 0;
   19475             : int epilogue_call_count_second = 0;
   19476             : int prologue_call_count_alloc = 0;
   19477             : int epilogue_call_count_alloc = 0;
   19478             : 
   19479          20 : void PrologueCallback(v8::Isolate* isolate,
   19480             :                       v8::GCType,
   19481             :                       v8::GCCallbackFlags flags) {
   19482          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19483          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19484          20 :   ++prologue_call_count;
   19485          20 : }
   19486             : 
   19487          20 : void EpilogueCallback(v8::Isolate* isolate,
   19488             :                       v8::GCType,
   19489             :                       v8::GCCallbackFlags flags) {
   19490          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19491          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19492          20 :   ++epilogue_call_count;
   19493          20 : }
   19494             : 
   19495             : 
   19496          20 : void PrologueCallbackSecond(v8::Isolate* isolate,
   19497             :                             v8::GCType,
   19498             :                             v8::GCCallbackFlags flags) {
   19499          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19500          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19501          20 :   ++prologue_call_count_second;
   19502          20 : }
   19503             : 
   19504             : 
   19505          20 : void EpilogueCallbackSecond(v8::Isolate* isolate,
   19506             :                             v8::GCType,
   19507             :                             v8::GCCallbackFlags flags) {
   19508          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19509          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19510          20 :   ++epilogue_call_count_second;
   19511          20 : }
   19512             : 
   19513          20 : void PrologueCallbackNew(v8::Isolate* isolate, v8::GCType,
   19514             :                          v8::GCCallbackFlags flags, void* data) {
   19515          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19516          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19517          20 :   ++*static_cast<int*>(data);
   19518          20 : }
   19519             : 
   19520          20 : void EpilogueCallbackNew(v8::Isolate* isolate, v8::GCType,
   19521             :                          v8::GCCallbackFlags flags, void* data) {
   19522          20 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19523          20 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19524          20 :   ++*static_cast<int*>(data);
   19525          20 : }
   19526             : 
   19527           5 : void PrologueCallbackAlloc(v8::Isolate* isolate,
   19528             :                            v8::GCType,
   19529             :                            v8::GCCallbackFlags flags) {
   19530           5 :   v8::HandleScope scope(isolate);
   19531             : 
   19532           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19533           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19534           5 :   ++prologue_call_count_alloc;
   19535             : 
   19536             :   // Simulate full heap to see if we will reenter this callback
   19537           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19538             : 
   19539           5 :   Local<Object> obj = Object::New(isolate);
   19540           5 :   CHECK(!obj.IsEmpty());
   19541             : 
   19542           5 :   CcTest::PreciseCollectAllGarbage();
   19543           5 : }
   19544             : 
   19545             : 
   19546           5 : void EpilogueCallbackAlloc(v8::Isolate* isolate,
   19547             :                            v8::GCType,
   19548             :                            v8::GCCallbackFlags flags) {
   19549           5 :   v8::HandleScope scope(isolate);
   19550             : 
   19551           5 :   CHECK_EQ(flags, v8::kNoGCCallbackFlags);
   19552           5 :   CHECK_EQ(gc_callbacks_isolate, isolate);
   19553           5 :   ++epilogue_call_count_alloc;
   19554             : 
   19555             :   // Simulate full heap to see if we will reenter this callback
   19556           5 :   i::heap::SimulateFullSpace(CcTest::heap()->new_space());
   19557             : 
   19558           5 :   Local<Object> obj = Object::New(isolate);
   19559           5 :   CHECK(!obj.IsEmpty());
   19560             : 
   19561           5 :   CcTest::PreciseCollectAllGarbage();
   19562           5 : }
   19563             : 
   19564             : 
   19565       25880 : TEST(GCCallbacksOld) {
   19566           5 :   LocalContext context;
   19567             : 
   19568           5 :   gc_callbacks_isolate = context->GetIsolate();
   19569             : 
   19570           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
   19571           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
   19572           5 :   CHECK_EQ(0, prologue_call_count);
   19573           5 :   CHECK_EQ(0, epilogue_call_count);
   19574           5 :   CcTest::CollectAllGarbage();
   19575           5 :   CHECK_EQ(1, prologue_call_count);
   19576           5 :   CHECK_EQ(1, epilogue_call_count);
   19577           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
   19578           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19579           5 :   CcTest::CollectAllGarbage();
   19580           5 :   CHECK_EQ(2, prologue_call_count);
   19581           5 :   CHECK_EQ(2, epilogue_call_count);
   19582           5 :   CHECK_EQ(1, prologue_call_count_second);
   19583           5 :   CHECK_EQ(1, epilogue_call_count_second);
   19584           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
   19585           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
   19586           5 :   CcTest::CollectAllGarbage();
   19587           5 :   CHECK_EQ(2, prologue_call_count);
   19588           5 :   CHECK_EQ(2, epilogue_call_count);
   19589           5 :   CHECK_EQ(2, prologue_call_count_second);
   19590           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19591           5 :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19592           5 :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19593           5 :   CcTest::CollectAllGarbage();
   19594           5 :   CHECK_EQ(2, prologue_call_count);
   19595           5 :   CHECK_EQ(2, epilogue_call_count);
   19596           5 :   CHECK_EQ(2, prologue_call_count_second);
   19597           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19598           5 : }
   19599             : 
   19600       25880 : TEST(GCCallbacksWithData) {
   19601           5 :   LocalContext context;
   19602             : 
   19603           5 :   gc_callbacks_isolate = context->GetIsolate();
   19604           5 :   int prologue1 = 0;
   19605           5 :   int epilogue1 = 0;
   19606           5 :   int prologue2 = 0;
   19607           5 :   int epilogue2 = 0;
   19608             : 
   19609           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue1);
   19610           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue1);
   19611           5 :   CHECK_EQ(0, prologue1);
   19612           5 :   CHECK_EQ(0, epilogue1);
   19613           5 :   CHECK_EQ(0, prologue2);
   19614           5 :   CHECK_EQ(0, epilogue2);
   19615           5 :   CcTest::CollectAllGarbage();
   19616           5 :   CHECK_EQ(1, prologue1);
   19617           5 :   CHECK_EQ(1, epilogue1);
   19618           5 :   CHECK_EQ(0, prologue2);
   19619           5 :   CHECK_EQ(0, epilogue2);
   19620           5 :   context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackNew, &prologue2);
   19621           5 :   context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackNew, &epilogue2);
   19622           5 :   CcTest::CollectAllGarbage();
   19623           5 :   CHECK_EQ(2, prologue1);
   19624           5 :   CHECK_EQ(2, epilogue1);
   19625           5 :   CHECK_EQ(1, prologue2);
   19626           5 :   CHECK_EQ(1, epilogue2);
   19627             :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   19628           5 :                                                   &prologue1);
   19629             :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   19630           5 :                                                   &epilogue1);
   19631           5 :   CcTest::CollectAllGarbage();
   19632           5 :   CHECK_EQ(2, prologue1);
   19633           5 :   CHECK_EQ(2, epilogue1);
   19634           5 :   CHECK_EQ(2, prologue2);
   19635           5 :   CHECK_EQ(2, epilogue2);
   19636             :   context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackNew,
   19637           5 :                                                   &prologue2);
   19638             :   context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackNew,
   19639           5 :                                                   &epilogue2);
   19640           5 :   CcTest::CollectAllGarbage();
   19641           5 :   CHECK_EQ(2, prologue1);
   19642           5 :   CHECK_EQ(2, epilogue1);
   19643           5 :   CHECK_EQ(2, prologue2);
   19644           5 :   CHECK_EQ(2, epilogue2);
   19645           5 : }
   19646             : 
   19647       25880 : TEST(GCCallbacks) {
   19648           5 :   LocalContext context;
   19649           5 :   v8::Isolate* isolate = context->GetIsolate();
   19650           5 :   gc_callbacks_isolate = isolate;
   19651           5 :   isolate->AddGCPrologueCallback(PrologueCallback);
   19652           5 :   isolate->AddGCEpilogueCallback(EpilogueCallback);
   19653           5 :   CHECK_EQ(0, prologue_call_count);
   19654           5 :   CHECK_EQ(0, epilogue_call_count);
   19655           5 :   CcTest::CollectAllGarbage();
   19656           5 :   CHECK_EQ(1, prologue_call_count);
   19657           5 :   CHECK_EQ(1, epilogue_call_count);
   19658           5 :   isolate->AddGCPrologueCallback(PrologueCallbackSecond);
   19659           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
   19660           5 :   CcTest::CollectAllGarbage();
   19661           5 :   CHECK_EQ(2, prologue_call_count);
   19662           5 :   CHECK_EQ(2, epilogue_call_count);
   19663           5 :   CHECK_EQ(1, prologue_call_count_second);
   19664           5 :   CHECK_EQ(1, epilogue_call_count_second);
   19665           5 :   isolate->RemoveGCPrologueCallback(PrologueCallback);
   19666           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallback);
   19667           5 :   CcTest::CollectAllGarbage();
   19668           5 :   CHECK_EQ(2, prologue_call_count);
   19669           5 :   CHECK_EQ(2, epilogue_call_count);
   19670           5 :   CHECK_EQ(2, prologue_call_count_second);
   19671           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19672           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
   19673           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
   19674           5 :   CcTest::CollectAllGarbage();
   19675           5 :   CHECK_EQ(2, prologue_call_count);
   19676           5 :   CHECK_EQ(2, epilogue_call_count);
   19677           5 :   CHECK_EQ(2, prologue_call_count_second);
   19678           5 :   CHECK_EQ(2, epilogue_call_count_second);
   19679             : 
   19680           5 :   CHECK_EQ(0, prologue_call_count_alloc);
   19681           5 :   CHECK_EQ(0, epilogue_call_count_alloc);
   19682           5 :   isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
   19683           5 :   isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
   19684           5 :   CcTest::PreciseCollectAllGarbage();
   19685           5 :   CHECK_EQ(1, prologue_call_count_alloc);
   19686           5 :   CHECK_EQ(1, epilogue_call_count_alloc);
   19687           5 :   isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
   19688           5 :   isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
   19689           5 : }
   19690             : 
   19691             : 
   19692       25881 : THREADED_TEST(TwoByteStringInOneByteCons) {
   19693             :   // See Chromium issue 47824.
   19694           6 :   LocalContext context;
   19695          12 :   v8::HandleScope scope(context->GetIsolate());
   19696             : 
   19697             :   const char* init_code =
   19698             :       "var str1 = 'abelspendabel';"
   19699             :       "var str2 = str1 + str1 + str1;"
   19700             :       "str2;";
   19701             :   Local<Value> result = CompileRun(init_code);
   19702             : 
   19703           6 :   Local<Value> indexof = CompileRun("str2.indexOf('els')");
   19704           6 :   Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
   19705             : 
   19706           6 :   CHECK(result->IsString());
   19707             :   i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
   19708             :   int length = string->length();
   19709           6 :   CHECK(string->IsOneByteRepresentation());
   19710             : 
   19711           6 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
   19712           6 :   i::Handle<i::String> flat_string = i::String::Flatten(i_isolate, string);
   19713             : 
   19714           6 :   CHECK(string->IsOneByteRepresentation());
   19715           6 :   CHECK(flat_string->IsOneByteRepresentation());
   19716             : 
   19717             :   // Create external resource.
   19718           6 :   uint16_t* uc16_buffer = new uint16_t[length + 1];
   19719             : 
   19720           6 :   i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
   19721           6 :   uc16_buffer[length] = 0;
   19722             : 
   19723           6 :   TestResource resource(uc16_buffer);
   19724             : 
   19725           6 :   flat_string->MakeExternal(&resource);
   19726             : 
   19727           6 :   CHECK(flat_string->IsTwoByteRepresentation());
   19728             : 
   19729             :   // If the cons string has been short-circuited, skip the following checks.
   19730           6 :   if (!string.is_identical_to(flat_string)) {
   19731             :     // At this point, we should have a Cons string which is flat and one-byte,
   19732             :     // with a first half that is a two-byte string (although it only contains
   19733             :     // one-byte characters). This is a valid sequence of steps, and it can
   19734             :     // happen in real pages.
   19735           6 :     CHECK(string->IsOneByteRepresentation());
   19736           6 :     i::ConsString cons = i::ConsString::cast(*string);
   19737          12 :     CHECK_EQ(0, cons->second()->length());
   19738           6 :     CHECK(cons->first()->IsTwoByteRepresentation());
   19739             :   }
   19740             : 
   19741             :   // Check that some string operations work.
   19742             : 
   19743             :   // Atom RegExp.
   19744             :   Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
   19745          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   19746             : 
   19747             :   // Nonatom RegExp.
   19748             :   reresult = CompileRun("str2.match(/abe./g).length;");
   19749          12 :   CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
   19750             : 
   19751             :   reresult = CompileRun("str2.search(/bel/g);");
   19752          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   19753             : 
   19754             :   reresult = CompileRun("str2.search(/be./g);");
   19755          12 :   CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
   19756             : 
   19757             :   ExpectTrue("/bel/g.test(str2);");
   19758             : 
   19759             :   ExpectTrue("/be./g.test(str2);");
   19760             : 
   19761             :   reresult = CompileRun("/bel/g.exec(str2);");
   19762           6 :   CHECK(!reresult->IsNull());
   19763             : 
   19764             :   reresult = CompileRun("/be./g.exec(str2);");
   19765           6 :   CHECK(!reresult->IsNull());
   19766             : 
   19767           6 :   ExpectString("str2.substring(2, 10);", "elspenda");
   19768             : 
   19769           6 :   ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
   19770             : 
   19771           6 :   ExpectString("str2.charAt(2);", "e");
   19772             : 
   19773           6 :   ExpectObject("str2.indexOf('els');", indexof);
   19774             : 
   19775           6 :   ExpectObject("str2.lastIndexOf('dab');", lastindexof);
   19776             : 
   19777             :   reresult = CompileRun("str2.charCodeAt(2);");
   19778          12 :   CHECK_EQ(static_cast<int32_t>('e'),
   19779             :            reresult->Int32Value(context.local()).FromJust());
   19780             :   // This avoids the GC from trying to free stack allocated resources.
   19781             :   i::Handle<i::ExternalTwoByteString>::cast(flat_string)
   19782          18 :       ->SetResource(i_isolate, nullptr);
   19783           6 : }
   19784             : 
   19785             : 
   19786       25880 : TEST(ContainsOnlyOneByte) {
   19787           5 :   v8::V8::Initialize();
   19788           5 :   v8::Isolate* isolate = CcTest::isolate();
   19789           5 :   v8::HandleScope scope(isolate);
   19790             :   // Make a buffer long enough that it won't automatically be converted.
   19791             :   const int length = 512;
   19792             :   // Ensure word aligned assignment.
   19793             :   const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
   19794           5 :   std::unique_ptr<uintptr_t[]> aligned_contents(new uintptr_t[aligned_length]);
   19795             :   uint16_t* string_contents =
   19796             :       reinterpret_cast<uint16_t*>(aligned_contents.get());
   19797             :   // Set to contain only one byte.
   19798        2560 :   for (int i = 0; i < length-1; i++) {
   19799        2555 :     string_contents[i] = 0x41;
   19800             :   }
   19801           5 :   string_contents[length-1] = 0;
   19802             :   // Simple case.
   19803             :   Local<String> string =
   19804             :       String::NewExternalTwoByte(
   19805           5 :           isolate, new TestResource(string_contents, nullptr, false))
   19806           5 :           .ToLocalChecked();
   19807           5 :   CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19808             :   // Counter example.
   19809             :   string = String::NewFromTwoByte(isolate, string_contents,
   19810             :                                   v8::NewStringType::kNormal)
   19811           5 :                .ToLocalChecked();
   19812           5 :   CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19813             :   // Test left right and balanced cons strings.
   19814           5 :   Local<String> base = v8_str("a");
   19815           5 :   Local<String> left = base;
   19816           5 :   Local<String> right = base;
   19817        5005 :   for (int i = 0; i < 1000; i++) {
   19818        5000 :     left = String::Concat(isolate, base, left);
   19819        5000 :     right = String::Concat(isolate, right, base);
   19820             :   }
   19821           5 :   Local<String> balanced = String::Concat(isolate, left, base);
   19822           5 :   balanced = String::Concat(isolate, balanced, right);
   19823           5 :   Local<String> cons_strings[] = {left, balanced, right};
   19824             :   Local<String> two_byte =
   19825             :       String::NewExternalTwoByte(
   19826           5 :           isolate, new TestResource(string_contents, nullptr, false))
   19827          10 :           .ToLocalChecked();
   19828             :   USE(two_byte); USE(cons_strings);
   19829          20 :   for (size_t i = 0; i < arraysize(cons_strings); i++) {
   19830             :     // Base assumptions.
   19831          15 :     string = cons_strings[i];
   19832          15 :     CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
   19833             :     // Test left and right concatentation.
   19834          15 :     string = String::Concat(isolate, two_byte, cons_strings[i]);
   19835          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19836          15 :     string = String::Concat(isolate, cons_strings[i], two_byte);
   19837          15 :     CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
   19838             :   }
   19839             :   // Set bits in different positions
   19840             :   // for strings of different lengths and alignments.
   19841          35 :   for (int alignment = 0; alignment < 7; alignment++) {
   19842         280 :     for (int size = 2; alignment + size < length; size *= 2) {
   19843             :       int zero_offset = size + alignment;
   19844         280 :       string_contents[zero_offset] = 0;
   19845       18130 :       for (int i = 0; i < size; i++) {
   19846       17850 :         int shift = 8 + (i % 7);
   19847       17850 :         string_contents[alignment + i] = 1 << shift;
   19848             :         string = String::NewExternalTwoByte(
   19849             :                      isolate, new TestResource(string_contents + alignment,
   19850       17850 :                                                nullptr, false))
   19851       17850 :                      .ToLocalChecked();
   19852       17850 :         CHECK_EQ(size, string->Length());
   19853       17850 :         CHECK(!string->ContainsOnlyOneByte());
   19854       17850 :         string_contents[alignment + i] = 0x41;
   19855             :       }
   19856         280 :       string_contents[zero_offset] = 0x41;
   19857             :     }
   19858           5 :   }
   19859           5 : }
   19860             : 
   19861             : 
   19862             : // Failed access check callback that performs a GC on each invocation.
   19863          75 : void FailedAccessCheckCallbackGC(Local<v8::Object> target,
   19864             :                                  v8::AccessType type,
   19865             :                                  Local<v8::Value> data) {
   19866          75 :   CcTest::CollectAllGarbage();
   19867             :   CcTest::isolate()->ThrowException(
   19868          75 :       v8::Exception::Error(v8_str("cross context")));
   19869          75 : }
   19870             : 
   19871             : 
   19872       25880 : TEST(GCInFailedAccessCheckCallback) {
   19873             :   // Install a failed access check callback that performs a GC on each
   19874             :   // invocation. Then force the callback to be called from va
   19875             : 
   19876           5 :   v8::V8::Initialize();
   19877           5 :   v8::Isolate* isolate = CcTest::isolate();
   19878             : 
   19879           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
   19880             : 
   19881           5 :   v8::HandleScope scope(isolate);
   19882             : 
   19883             :   // Create an ObjectTemplate for global objects and install access
   19884             :   // check callbacks that will block access.
   19885             :   v8::Local<v8::ObjectTemplate> global_template =
   19886           5 :       v8::ObjectTemplate::New(isolate);
   19887           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   19888             : 
   19889             :   // Create a context and set an x property on it's global object.
   19890          10 :   LocalContext context0(nullptr, global_template);
   19891          25 :   CHECK(context0->Global()
   19892             :             ->Set(context0.local(), v8_str("x"), v8_num(42))
   19893             :             .FromJust());
   19894           5 :   v8::Local<v8::Object> global0 = context0->Global();
   19895             : 
   19896             :   // Create a context with a different security token so that the
   19897             :   // failed access check callback will be called on each access.
   19898          10 :   LocalContext context1(nullptr, global_template);
   19899          25 :   CHECK(context1->Global()
   19900             :             ->Set(context1.local(), v8_str("other"), global0)
   19901             :             .FromJust());
   19902             : 
   19903          10 :   v8::TryCatch try_catch(isolate);
   19904             : 
   19905             :   // Get property with failed access check.
   19906           5 :   CHECK(CompileRun("other.x").IsEmpty());
   19907           5 :   CHECK(try_catch.HasCaught());
   19908           5 :   try_catch.Reset();
   19909             : 
   19910             :   // Get element with failed access check.
   19911           5 :   CHECK(CompileRun("other[0]").IsEmpty());
   19912           5 :   CHECK(try_catch.HasCaught());
   19913           5 :   try_catch.Reset();
   19914             : 
   19915             :   // Set property with failed access check.
   19916           5 :   CHECK(CompileRun("other.x = new Object()").IsEmpty());
   19917           5 :   CHECK(try_catch.HasCaught());
   19918           5 :   try_catch.Reset();
   19919             : 
   19920             :   // Set element with failed access check.
   19921           5 :   CHECK(CompileRun("other[0] = new Object()").IsEmpty());
   19922           5 :   CHECK(try_catch.HasCaught());
   19923           5 :   try_catch.Reset();
   19924             : 
   19925             :   // Get property attribute with failed access check.
   19926           5 :   CHECK(CompileRun("\'x\' in other").IsEmpty());
   19927           5 :   CHECK(try_catch.HasCaught());
   19928           5 :   try_catch.Reset();
   19929             : 
   19930             :   // Get property attribute for element with failed access check.
   19931           5 :   CHECK(CompileRun("0 in other").IsEmpty());
   19932           5 :   CHECK(try_catch.HasCaught());
   19933           5 :   try_catch.Reset();
   19934             : 
   19935             :   // Delete property.
   19936           5 :   CHECK(CompileRun("delete other.x").IsEmpty());
   19937           5 :   CHECK(try_catch.HasCaught());
   19938           5 :   try_catch.Reset();
   19939             : 
   19940             :   // Delete element.
   19941          10 :   CHECK(global0->Delete(context1.local(), 0).IsNothing());
   19942           5 :   CHECK(try_catch.HasCaught());
   19943           5 :   try_catch.Reset();
   19944             : 
   19945             :   // DefineAccessor.
   19946          20 :   CHECK(global0
   19947             :             ->SetAccessor(context1.local(), v8_str("x"), GetXValue, nullptr,
   19948             :                           v8_str("x"))
   19949             :             .IsNothing());
   19950           5 :   CHECK(try_catch.HasCaught());
   19951           5 :   try_catch.Reset();
   19952             : 
   19953             :   // Define JavaScript accessor.
   19954           5 :   CHECK(CompileRun(
   19955             :             "Object.prototype.__defineGetter__.call("
   19956             :             "    other, \'x\', function() { return 42; })").IsEmpty());
   19957           5 :   CHECK(try_catch.HasCaught());
   19958           5 :   try_catch.Reset();
   19959             : 
   19960             :   // LookupAccessor.
   19961           5 :   CHECK(CompileRun(
   19962             :             "Object.prototype.__lookupGetter__.call("
   19963             :             "    other, \'x\')").IsEmpty());
   19964           5 :   CHECK(try_catch.HasCaught());
   19965           5 :   try_catch.Reset();
   19966             : 
   19967             :   // HasOwnElement.
   19968           5 :   CHECK(CompileRun(
   19969             :             "Object.prototype.hasOwnProperty.call("
   19970             :             "other, \'0\')").IsEmpty());
   19971           5 :   CHECK(try_catch.HasCaught());
   19972           5 :   try_catch.Reset();
   19973             : 
   19974          10 :   CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
   19975           5 :   CHECK(try_catch.HasCaught());
   19976           5 :   try_catch.Reset();
   19977             : 
   19978          15 :   CHECK(
   19979             :       global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
   19980           5 :   CHECK(try_catch.HasCaught());
   19981           5 :   try_catch.Reset();
   19982             : 
   19983          15 :   CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
   19984             :             .IsNothing());
   19985           5 :   CHECK(try_catch.HasCaught());
   19986           5 :   try_catch.Reset();
   19987             : 
   19988             :   // Reset the failed access check callback so it does not influence
   19989             :   // the other tests.
   19990          10 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   19991           5 : }
   19992             : 
   19993             : 
   19994       25880 : TEST(IsolateNewDispose) {
   19995           5 :   v8::Isolate* current_isolate = CcTest::isolate();
   19996             :   v8::Isolate::CreateParams create_params;
   19997           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   19998           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   19999           5 :   CHECK_NOT_NULL(isolate);
   20000           5 :   CHECK(current_isolate != isolate);
   20001           5 :   CHECK(current_isolate == CcTest::isolate());
   20002             : 
   20003           5 :   isolate->SetFatalErrorHandler(StoringErrorCallback);
   20004           5 :   last_location = last_message = nullptr;
   20005           5 :   isolate->Dispose();
   20006           5 :   CHECK(!last_location);
   20007           5 :   CHECK(!last_message);
   20008           5 : }
   20009             : 
   20010             : 
   20011       25880 : UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
   20012             :   v8::Isolate::CreateParams create_params;
   20013           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20014           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20015             :   {
   20016             :     v8::Isolate::Scope i_scope(isolate);
   20017          10 :     v8::HandleScope scope(isolate);
   20018           5 :     LocalContext context(isolate);
   20019             :     // Run something in this isolate.
   20020             :     ExpectTrue("true");
   20021           5 :     isolate->SetFatalErrorHandler(StoringErrorCallback);
   20022           5 :     last_location = last_message = nullptr;
   20023             :     // Still entered, should fail.
   20024           5 :     isolate->Dispose();
   20025           5 :     CHECK(last_location);
   20026           5 :     CHECK(last_message);
   20027             :   }
   20028           5 :   isolate->Dispose();
   20029           5 : }
   20030             : 
   20031             : 
   20032          40 : static void BreakArrayGuarantees(const char* script) {
   20033             :   v8::Isolate::CreateParams create_params;
   20034          40 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20035          40 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20036          40 :   isolate1->Enter();
   20037             :   v8::Persistent<v8::Context> context1;
   20038             :   {
   20039          40 :     v8::HandleScope scope(isolate1);
   20040          80 :     context1.Reset(isolate1, Context::New(isolate1));
   20041             :   }
   20042             : 
   20043             :   {
   20044          40 :     v8::HandleScope scope(isolate1);
   20045             :     v8::Local<v8::Context> context =
   20046             :         v8::Local<v8::Context>::New(isolate1, context1);
   20047             :     v8::Context::Scope context_scope(context);
   20048             :     v8::internal::Isolate* i_isolate =
   20049             :         reinterpret_cast<v8::internal::Isolate*>(isolate1);
   20050          40 :     CHECK(i_isolate->IsNoElementsProtectorIntact());
   20051             :     // Run something in new isolate.
   20052             :     CompileRun(script);
   20053          80 :     CHECK(!i_isolate->IsNoElementsProtectorIntact());
   20054             :   }
   20055          40 :   isolate1->Exit();
   20056          40 :   isolate1->Dispose();
   20057          40 : }
   20058             : 
   20059             : 
   20060       25880 : TEST(VerifyArrayPrototypeGuarantees) {
   20061             :   // Break fast array hole handling by element changes.
   20062           5 :   BreakArrayGuarantees("[].__proto__[1] = 3;");
   20063           5 :   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   20064           5 :   BreakArrayGuarantees("Array.prototype.push(1);");
   20065           5 :   BreakArrayGuarantees("Array.prototype.unshift(1);");
   20066             :   // Break fast array hole handling by changing length.
   20067           5 :   BreakArrayGuarantees("Array.prototype.length = 30;");
   20068             :   // Break fast array hole handling by prototype structure changes.
   20069           5 :   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   20070             :   // By sending elements to dictionary mode.
   20071             :   BreakArrayGuarantees(
   20072             :       "Object.defineProperty(Array.prototype, 0, {"
   20073           5 :       "  get: function() { return 3; }});");
   20074             :   BreakArrayGuarantees(
   20075             :       "Object.defineProperty(Object.prototype, 0, {"
   20076           5 :       "  get: function() { return 3; }});");
   20077           5 : }
   20078             : 
   20079             : 
   20080       25880 : TEST(RunTwoIsolatesOnSingleThread) {
   20081             :   // Run isolate 1.
   20082             :   v8::Isolate::CreateParams create_params;
   20083           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20084           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   20085           5 :   isolate1->Enter();
   20086             :   v8::Persistent<v8::Context> context1;
   20087             :   {
   20088           5 :     v8::HandleScope scope(isolate1);
   20089          10 :     context1.Reset(isolate1, Context::New(isolate1));
   20090             :   }
   20091             : 
   20092             :   {
   20093           5 :     v8::HandleScope scope(isolate1);
   20094             :     v8::Local<v8::Context> context =
   20095             :         v8::Local<v8::Context>::New(isolate1, context1);
   20096             :     v8::Context::Scope context_scope(context);
   20097             :     // Run something in new isolate.
   20098             :     CompileRun("var foo = 'isolate 1';");
   20099          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20100             :   }
   20101             : 
   20102             :   // Run isolate 2.
   20103           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   20104             :   v8::Persistent<v8::Context> context2;
   20105             : 
   20106             :   {
   20107             :     v8::Isolate::Scope iscope(isolate2);
   20108          10 :     v8::HandleScope scope(isolate2);
   20109          10 :     context2.Reset(isolate2, Context::New(isolate2));
   20110             :     v8::Local<v8::Context> context =
   20111             :         v8::Local<v8::Context>::New(isolate2, context2);
   20112             :     v8::Context::Scope context_scope(context);
   20113             : 
   20114             :     // Run something in new isolate.
   20115             :     CompileRun("var foo = 'isolate 2';");
   20116           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20117             :   }
   20118             : 
   20119             :   {
   20120           5 :     v8::HandleScope scope(isolate1);
   20121             :     v8::Local<v8::Context> context =
   20122             :         v8::Local<v8::Context>::New(isolate1, context1);
   20123             :     v8::Context::Scope context_scope(context);
   20124             :     // Now again in isolate 1
   20125          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20126             :   }
   20127             : 
   20128           5 :   isolate1->Exit();
   20129             : 
   20130             :   // Run some stuff in default isolate.
   20131             :   v8::Persistent<v8::Context> context_default;
   20132             :   {
   20133           5 :     v8::Isolate* isolate = CcTest::isolate();
   20134             :     v8::Isolate::Scope iscope(isolate);
   20135          10 :     v8::HandleScope scope(isolate);
   20136          10 :     context_default.Reset(isolate, Context::New(isolate));
   20137             :   }
   20138             : 
   20139             :   {
   20140           5 :     v8::HandleScope scope(CcTest::isolate());
   20141             :     v8::Local<v8::Context> context =
   20142           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20143             :     v8::Context::Scope context_scope(context);
   20144             :     // Variables in other isolates should be not available, verify there
   20145             :     // is an exception.
   20146             :     ExpectTrue("function f() {"
   20147             :                "  try {"
   20148             :                "    foo;"
   20149             :                "    return false;"
   20150             :                "  } catch(e) {"
   20151             :                "    return true;"
   20152             :                "  }"
   20153             :                "};"
   20154             :                "var isDefaultIsolate = true;"
   20155           5 :                "f()");
   20156             :   }
   20157             : 
   20158           5 :   isolate1->Enter();
   20159             : 
   20160             :   {
   20161             :     v8::Isolate::Scope iscope(isolate2);
   20162          10 :     v8::HandleScope scope(isolate2);
   20163             :     v8::Local<v8::Context> context =
   20164             :         v8::Local<v8::Context>::New(isolate2, context2);
   20165             :     v8::Context::Scope context_scope(context);
   20166           5 :     ExpectString("function f() { return foo; }; f()", "isolate 2");
   20167             :   }
   20168             : 
   20169             :   {
   20170           5 :     v8::HandleScope scope(v8::Isolate::GetCurrent());
   20171             :     v8::Local<v8::Context> context =
   20172           5 :         v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
   20173             :     v8::Context::Scope context_scope(context);
   20174          10 :     ExpectString("function f() { return foo; }; f()", "isolate 1");
   20175             :   }
   20176             : 
   20177             :   {
   20178             :     v8::Isolate::Scope iscope(isolate2);
   20179             :     context2.Reset();
   20180             :   }
   20181             : 
   20182             :   context1.Reset();
   20183           5 :   isolate1->Exit();
   20184             : 
   20185           5 :   isolate2->SetFatalErrorHandler(StoringErrorCallback);
   20186           5 :   last_location = last_message = nullptr;
   20187             : 
   20188           5 :   isolate1->Dispose();
   20189           5 :   CHECK(!last_location);
   20190           5 :   CHECK(!last_message);
   20191             : 
   20192           5 :   isolate2->Dispose();
   20193           5 :   CHECK(!last_location);
   20194           5 :   CHECK(!last_message);
   20195             : 
   20196             :   // Check that default isolate still runs.
   20197             :   {
   20198           5 :     v8::HandleScope scope(CcTest::isolate());
   20199             :     v8::Local<v8::Context> context =
   20200           5 :         v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
   20201             :     v8::Context::Scope context_scope(context);
   20202           5 :     ExpectTrue("function f() { return isDefaultIsolate; }; f()");
   20203             :   }
   20204           5 : }
   20205             : 
   20206             : 
   20207          20 : static int CalcFibonacci(v8::Isolate* isolate, int limit) {
   20208             :   v8::Isolate::Scope isolate_scope(isolate);
   20209          40 :   v8::HandleScope scope(isolate);
   20210          20 :   LocalContext context(isolate);
   20211             :   i::ScopedVector<char> code(1024);
   20212             :   i::SNPrintF(code, "function fib(n) {"
   20213             :                     "  if (n <= 2) return 1;"
   20214             :                     "  return fib(n-1) + fib(n-2);"
   20215             :                     "}"
   20216          20 :                     "fib(%d)", limit);
   20217             :   Local<Value> value = CompileRun(code.start());
   20218          20 :   CHECK(value->IsNumber());
   20219          60 :   return static_cast<int>(value->NumberValue(context.local()).FromJust());
   20220             : }
   20221             : 
   20222           5 : class IsolateThread : public v8::base::Thread {
   20223             :  public:
   20224             :   explicit IsolateThread(int fib_limit)
   20225          10 :       : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
   20226             : 
   20227          10 :   void Run() override {
   20228             :     v8::Isolate::CreateParams create_params;
   20229          10 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20230          10 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20231          10 :     result_ = CalcFibonacci(isolate, fib_limit_);
   20232          10 :     isolate->Dispose();
   20233          10 :   }
   20234             : 
   20235             :   int result() { return result_; }
   20236             : 
   20237             :  private:
   20238             :   int fib_limit_;
   20239             :   int result_;
   20240             : };
   20241             : 
   20242             : 
   20243       25880 : TEST(MultipleIsolatesOnIndividualThreads) {
   20244             :   IsolateThread thread1(21);
   20245             :   IsolateThread thread2(12);
   20246             : 
   20247             :   // Compute some fibonacci numbers on 3 threads in 3 isolates.
   20248           5 :   thread1.Start();
   20249           5 :   thread2.Start();
   20250             : 
   20251           5 :   int result1 = CalcFibonacci(CcTest::isolate(), 21);
   20252           5 :   int result2 = CalcFibonacci(CcTest::isolate(), 12);
   20253             : 
   20254           5 :   thread1.Join();
   20255           5 :   thread2.Join();
   20256             : 
   20257             :   // Compare results. The actual fibonacci numbers for 12 and 21 are taken
   20258             :   // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
   20259           5 :   CHECK_EQ(result1, 10946);
   20260           5 :   CHECK_EQ(result2, 144);
   20261           5 :   CHECK_EQ(result1, thread1.result());
   20262           5 :   CHECK_EQ(result2, thread2.result());
   20263           5 : }
   20264             : 
   20265             : 
   20266       25880 : TEST(IsolateDifferentContexts) {
   20267             :   v8::Isolate::CreateParams create_params;
   20268           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20269           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   20270             :   Local<v8::Context> context;
   20271             :   {
   20272             :     v8::Isolate::Scope isolate_scope(isolate);
   20273          10 :     v8::HandleScope handle_scope(isolate);
   20274           5 :     context = v8::Context::New(isolate);
   20275             :     v8::Context::Scope context_scope(context);
   20276             :     Local<Value> v = CompileRun("2");
   20277           5 :     CHECK(v->IsNumber());
   20278          10 :     CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
   20279             :   }
   20280             :   {
   20281             :     v8::Isolate::Scope isolate_scope(isolate);
   20282          10 :     v8::HandleScope handle_scope(isolate);
   20283           5 :     context = v8::Context::New(isolate);
   20284             :     v8::Context::Scope context_scope(context);
   20285             :     Local<Value> v = CompileRun("22");
   20286           5 :     CHECK(v->IsNumber());
   20287          10 :     CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
   20288             :   }
   20289           5 :   isolate->Dispose();
   20290           5 : }
   20291             : 
   20292          20 : class InitDefaultIsolateThread : public v8::base::Thread {
   20293             :  public:
   20294             :   enum TestCase {
   20295             :     SetFatalHandler,
   20296             :     SetCounterFunction,
   20297             :     SetCreateHistogramFunction,
   20298             :     SetAddHistogramSampleFunction
   20299             :   };
   20300             : 
   20301             :   explicit InitDefaultIsolateThread(TestCase testCase)
   20302             :       : Thread(Options("InitDefaultIsolateThread")),
   20303             :         testCase_(testCase),
   20304          20 :         result_(false) {}
   20305             : 
   20306          20 :   void Run() override {
   20307             :     v8::Isolate::CreateParams create_params;
   20308          20 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   20309          20 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   20310          20 :     isolate->Enter();
   20311          20 :     switch (testCase_) {
   20312             :       case SetFatalHandler:
   20313           5 :         isolate->SetFatalErrorHandler(nullptr);
   20314           5 :         break;
   20315             : 
   20316             :       case SetCounterFunction:
   20317           5 :         CcTest::isolate()->SetCounterFunction(nullptr);
   20318           5 :         break;
   20319             : 
   20320             :       case SetCreateHistogramFunction:
   20321           5 :         CcTest::isolate()->SetCreateHistogramFunction(nullptr);
   20322           5 :         break;
   20323             : 
   20324             :       case SetAddHistogramSampleFunction:
   20325           5 :         CcTest::isolate()->SetAddHistogramSampleFunction(nullptr);
   20326           5 :         break;
   20327             :     }
   20328          20 :     isolate->Exit();
   20329          20 :     isolate->Dispose();
   20330          20 :     result_ = true;
   20331          20 :   }
   20332             : 
   20333             :   bool result() { return result_; }
   20334             : 
   20335             :  private:
   20336             :   TestCase testCase_;
   20337             :   bool result_;
   20338             : };
   20339             : 
   20340             : 
   20341          20 : static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
   20342             :   InitDefaultIsolateThread thread(testCase);
   20343          20 :   thread.Start();
   20344          20 :   thread.Join();
   20345          20 :   CHECK(thread.result());
   20346          20 : }
   20347             : 
   20348       25880 : TEST(InitializeDefaultIsolateOnSecondaryThread_FatalHandler) {
   20349           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
   20350           5 : }
   20351             : 
   20352       25880 : TEST(InitializeDefaultIsolateOnSecondaryThread_CounterFunction) {
   20353           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
   20354           5 : }
   20355             : 
   20356       25880 : TEST(InitializeDefaultIsolateOnSecondaryThread_CreateHistogramFunction) {
   20357           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
   20358           5 : }
   20359             : 
   20360       25880 : TEST(InitializeDefaultIsolateOnSecondaryThread_AddHistogramSampleFunction) {
   20361           5 :   InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
   20362           5 : }
   20363             : 
   20364             : 
   20365       25880 : TEST(StringCheckMultipleContexts) {
   20366             :   const char* code =
   20367             :       "(function() { return \"a\".charAt(0); })()";
   20368             : 
   20369             :   {
   20370             :     // Run the code twice in the first context to initialize the call IC.
   20371           5 :     LocalContext context1;
   20372          10 :     v8::HandleScope scope(context1->GetIsolate());
   20373           5 :     ExpectString(code, "a");
   20374          10 :     ExpectString(code, "a");
   20375             :   }
   20376             : 
   20377             :   {
   20378             :     // Change the String.prototype in the second context and check
   20379             :     // that the right function gets called.
   20380           5 :     LocalContext context2;
   20381          10 :     v8::HandleScope scope(context2->GetIsolate());
   20382             :     CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
   20383          10 :     ExpectString(code, "not a");
   20384             :   }
   20385           5 : }
   20386             : 
   20387             : 
   20388       25880 : TEST(NumberCheckMultipleContexts) {
   20389             :   const char* code =
   20390             :       "(function() { return (42).toString(); })()";
   20391             : 
   20392             :   {
   20393             :     // Run the code twice in the first context to initialize the call IC.
   20394           5 :     LocalContext context1;
   20395          10 :     v8::HandleScope scope(context1->GetIsolate());
   20396           5 :     ExpectString(code, "42");
   20397          10 :     ExpectString(code, "42");
   20398             :   }
   20399             : 
   20400             :   {
   20401             :     // Change the Number.prototype in the second context and check
   20402             :     // that the right function gets called.
   20403           5 :     LocalContext context2;
   20404          10 :     v8::HandleScope scope(context2->GetIsolate());
   20405             :     CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
   20406          10 :     ExpectString(code, "not 42");
   20407             :   }
   20408           5 : }
   20409             : 
   20410             : 
   20411       25880 : TEST(BooleanCheckMultipleContexts) {
   20412             :   const char* code =
   20413             :       "(function() { return true.toString(); })()";
   20414             : 
   20415             :   {
   20416             :     // Run the code twice in the first context to initialize the call IC.
   20417           5 :     LocalContext context1;
   20418          10 :     v8::HandleScope scope(context1->GetIsolate());
   20419           5 :     ExpectString(code, "true");
   20420          10 :     ExpectString(code, "true");
   20421             :   }
   20422             : 
   20423             :   {
   20424             :     // Change the Boolean.prototype in the second context and check
   20425             :     // that the right function gets called.
   20426           5 :     LocalContext context2;
   20427          10 :     v8::HandleScope scope(context2->GetIsolate());
   20428             :     CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
   20429          10 :     ExpectString(code, "");
   20430             :   }
   20431           5 : }
   20432             : 
   20433             : 
   20434       25880 : TEST(DontDeleteCellLoadIC) {
   20435             :   const char* function_code =
   20436             :       "function readCell() { while (true) { return cell; } }";
   20437             : 
   20438             :   {
   20439             :     // Run the code twice in the first context to initialize the load
   20440             :     // IC for a don't delete cell.
   20441           5 :     LocalContext context1;
   20442          10 :     v8::HandleScope scope(context1->GetIsolate());
   20443             :     CompileRun("var cell = \"first\";");
   20444           5 :     ExpectBoolean("delete cell", false);
   20445             :     CompileRun(function_code);
   20446           5 :     ExpectString("readCell()", "first");
   20447          10 :     ExpectString("readCell()", "first");
   20448             :   }
   20449             : 
   20450             :   {
   20451             :     // Use a deletable cell in the second context.
   20452           5 :     LocalContext context2;
   20453          10 :     v8::HandleScope scope(context2->GetIsolate());
   20454             :     CompileRun("cell = \"second\";");
   20455             :     CompileRun(function_code);
   20456           5 :     ExpectString("readCell()", "second");
   20457           5 :     ExpectBoolean("delete cell", true);
   20458             :     ExpectString("(function() {"
   20459             :                  "  try {"
   20460             :                  "    return readCell();"
   20461             :                  "  } catch(e) {"
   20462             :                  "    return e.toString();"
   20463             :                  "  }"
   20464             :                  "})()",
   20465           5 :                  "ReferenceError: cell is not defined");
   20466             :     CompileRun("cell = \"new_second\";");
   20467           5 :     CcTest::CollectAllGarbage();
   20468           5 :     ExpectString("readCell()", "new_second");
   20469          10 :     ExpectString("readCell()", "new_second");
   20470             :   }
   20471           5 : }
   20472             : 
   20473             : 
   20474          10 : class Visitor42 : public v8::PersistentHandleVisitor {
   20475             :  public:
   20476             :   explicit Visitor42(v8::Persistent<v8::Object>* object)
   20477          10 :       : counter_(0), object_(object) { }
   20478             : 
   20479          10 :   void VisitPersistentHandle(Persistent<Value>* value,
   20480             :                              uint16_t class_id) override {
   20481          10 :     if (class_id != 42) return;
   20482          10 :     CHECK_EQ(42, value->WrapperClassId());
   20483          10 :     v8::Isolate* isolate = CcTest::isolate();
   20484          10 :     v8::HandleScope handle_scope(isolate);
   20485             :     v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
   20486          10 :     v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
   20487          10 :     CHECK(handle->IsObject());
   20488          20 :     CHECK(Local<Object>::Cast(handle)
   20489             :               ->Equals(isolate->GetCurrentContext(), object)
   20490             :               .FromJust());
   20491          10 :     ++counter_;
   20492             :   }
   20493             : 
   20494             :   int counter_;
   20495             :   v8::Persistent<v8::Object>* object_;
   20496             : };
   20497             : 
   20498             : 
   20499       25880 : TEST(PersistentHandleVisitor) {
   20500           5 :   LocalContext context;
   20501           5 :   v8::Isolate* isolate = context->GetIsolate();
   20502          10 :   v8::HandleScope scope(isolate);
   20503           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20504           5 :   CHECK_EQ(0, object.WrapperClassId());
   20505             :   object.SetWrapperClassId(42);
   20506           5 :   CHECK_EQ(42, object.WrapperClassId());
   20507             : 
   20508             :   Visitor42 visitor(&object);
   20509           5 :   isolate->VisitHandlesWithClassIds(&visitor);
   20510           5 :   CHECK_EQ(1, visitor.counter_);
   20511             : 
   20512           5 :   object.Reset();
   20513           5 : }
   20514             : 
   20515             : 
   20516       25880 : TEST(WrapperClassId) {
   20517           5 :   LocalContext context;
   20518           5 :   v8::Isolate* isolate = context->GetIsolate();
   20519          10 :   v8::HandleScope scope(isolate);
   20520           5 :   v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
   20521           5 :   CHECK_EQ(0, object.WrapperClassId());
   20522             :   object.SetWrapperClassId(65535);
   20523           5 :   CHECK_EQ(65535, object.WrapperClassId());
   20524           5 :   object.Reset();
   20525           5 : }
   20526             : 
   20527             : 
   20528       25880 : TEST(PersistentHandleInNewSpaceVisitor) {
   20529           5 :   LocalContext context;
   20530           5 :   v8::Isolate* isolate = context->GetIsolate();
   20531          10 :   v8::HandleScope scope(isolate);
   20532           5 :   v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
   20533           5 :   CHECK_EQ(0, object1.WrapperClassId());
   20534             :   object1.SetWrapperClassId(42);
   20535           5 :   CHECK_EQ(42, object1.WrapperClassId());
   20536             : 
   20537           5 :   CcTest::CollectAllGarbage();
   20538           5 :   CcTest::CollectAllGarbage();
   20539             : 
   20540           5 :   v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
   20541           5 :   CHECK_EQ(0, object2.WrapperClassId());
   20542             :   object2.SetWrapperClassId(42);
   20543           5 :   CHECK_EQ(42, object2.WrapperClassId());
   20544             : 
   20545             :   Visitor42 visitor(&object2);
   20546             : #if __clang__
   20547             : #pragma clang diagnostic push
   20548             : #pragma clang diagnostic ignored "-Wdeprecated"
   20549             : #endif
   20550             :   // VisitHandlesForPartialDependence is marked deprecated. This test will be
   20551             :   // removed with the API method.
   20552           5 :   isolate->VisitHandlesForPartialDependence(&visitor);
   20553             : #if __clang__
   20554             : #pragma clang diagnostic pop
   20555             : #endif
   20556             : 
   20557           5 :   CHECK_EQ(1, visitor.counter_);
   20558             : 
   20559             :   object1.Reset();
   20560           5 :   object2.Reset();
   20561           5 : }
   20562             : 
   20563             : 
   20564       25880 : TEST(RegExp) {
   20565           5 :   LocalContext context;
   20566          10 :   v8::HandleScope scope(context->GetIsolate());
   20567             : 
   20568             :   v8::Local<v8::RegExp> re =
   20569           5 :       v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
   20570           5 :           .ToLocalChecked();
   20571           5 :   CHECK(re->IsRegExp());
   20572          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
   20573           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20574             : 
   20575             :   re = v8::RegExp::New(context.local(), v8_str("bar"),
   20576             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20577           5 :                                                       v8::RegExp::kGlobal))
   20578           5 :            .ToLocalChecked();
   20579           5 :   CHECK(re->IsRegExp());
   20580          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
   20581           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
   20582             :            static_cast<int>(re->GetFlags()));
   20583             : 
   20584             :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20585             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20586           5 :                                                       v8::RegExp::kMultiline))
   20587           5 :            .ToLocalChecked();
   20588           5 :   CHECK(re->IsRegExp());
   20589          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20590           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20591             :            static_cast<int>(re->GetFlags()));
   20592             : 
   20593             :   re = v8::RegExp::New(context.local(), v8_str("baz"),
   20594             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
   20595           5 :                                                       v8::RegExp::kSticky))
   20596           5 :            .ToLocalChecked();
   20597           5 :   CHECK(re->IsRegExp());
   20598          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
   20599           5 :   CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
   20600             :            static_cast<int>(re->GetFlags()));
   20601             : 
   20602             :   re = CompileRun("/quux/").As<v8::RegExp>();
   20603           5 :   CHECK(re->IsRegExp());
   20604          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20605           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20606             : 
   20607             :   re = CompileRun("/quux/gm").As<v8::RegExp>();
   20608           5 :   CHECK(re->IsRegExp());
   20609          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
   20610           5 :   CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
   20611             :            static_cast<int>(re->GetFlags()));
   20612             : 
   20613             :   // Override the RegExp constructor and check the API constructor
   20614             :   // still works.
   20615             :   CompileRun("RegExp = function() {}");
   20616             : 
   20617           5 :   re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
   20618           5 :            .ToLocalChecked();
   20619           5 :   CHECK(re->IsRegExp());
   20620          20 :   CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
   20621           5 :   CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
   20622             : 
   20623             :   re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
   20624             :                        static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
   20625           5 :                                                       v8::RegExp::kMultiline))
   20626           5 :            .ToLocalChecked();
   20627           5 :   CHECK(re->IsRegExp());
   20628          20 :   CHECK(
   20629             :       re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
   20630           5 :   CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
   20631             :            static_cast<int>(re->GetFlags()));
   20632             : 
   20633          25 :   CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
   20634             :   ExpectTrue("re.test('FoobarbaZ')");
   20635             : 
   20636             :   // RegExps are objects on which you can set properties.
   20637             :   re->Set(context.local(), v8_str("property"),
   20638          20 :           v8::Integer::New(context->GetIsolate(), 32))
   20639          10 :       .FromJust();
   20640             :   v8::Local<v8::Value> value(CompileRun("re.property"));
   20641          10 :   CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
   20642             : 
   20643          10 :   v8::TryCatch try_catch(context->GetIsolate());
   20644          10 :   CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
   20645             :             .IsEmpty());
   20646           5 :   CHECK(try_catch.HasCaught());
   20647          25 :   CHECK(context->Global()
   20648             :             ->Set(context.local(), v8_str("ex"), try_catch.Exception())
   20649             :             .FromJust());
   20650           5 :   ExpectTrue("ex instanceof SyntaxError");
   20651           5 : }
   20652             : 
   20653             : 
   20654       25881 : THREADED_TEST(Equals) {
   20655           6 :   LocalContext localContext;
   20656          12 :   v8::HandleScope handleScope(localContext->GetIsolate());
   20657             : 
   20658           6 :   v8::Local<v8::Object> globalProxy = localContext->Global();
   20659           6 :   v8::Local<Value> global = globalProxy->GetPrototype();
   20660             : 
   20661           6 :   CHECK(global->StrictEquals(global));
   20662           6 :   CHECK(!global->StrictEquals(globalProxy));
   20663           6 :   CHECK(!globalProxy->StrictEquals(global));
   20664           6 :   CHECK(globalProxy->StrictEquals(globalProxy));
   20665             : 
   20666          12 :   CHECK(global->Equals(localContext.local(), global).FromJust());
   20667          12 :   CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
   20668          12 :   CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
   20669          18 :   CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
   20670           6 : }
   20671             : 
   20672             : 
   20673           5 : static void Getter(v8::Local<v8::Name> property,
   20674             :                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   20675           5 :   info.GetReturnValue().Set(v8_str("42!"));
   20676           5 : }
   20677             : 
   20678             : 
   20679           5 : static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
   20680           5 :   v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
   20681             :   result->Set(info.GetIsolate()->GetCurrentContext(), 0,
   20682          15 :               v8_str("universalAnswer"))
   20683          10 :       .FromJust();
   20684             :   info.GetReturnValue().Set(result);
   20685           5 : }
   20686             : 
   20687             : 
   20688       25880 : TEST(NamedEnumeratorAndForIn) {
   20689           5 :   LocalContext context;
   20690           5 :   v8::Isolate* isolate = context->GetIsolate();
   20691          10 :   v8::HandleScope handle_scope(isolate);
   20692           5 :   v8::Context::Scope context_scope(context.local());
   20693             : 
   20694           5 :   v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
   20695             :   tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20696           5 :       Getter, nullptr, nullptr, nullptr, Enumerator));
   20697          30 :   CHECK(context->Global()
   20698             :             ->Set(context.local(), v8_str("o"),
   20699             :                   tmpl->NewInstance(context.local()).ToLocalChecked())
   20700             :             .FromJust());
   20701             :   v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
   20702             :       CompileRun("var result = []; for (var k in o) result.push(k); result"));
   20703           5 :   CHECK_EQ(1u, result->Length());
   20704          20 :   CHECK(v8_str("universalAnswer")
   20705             :             ->Equals(context.local(),
   20706             :                      result->Get(context.local(), 0).ToLocalChecked())
   20707           5 :             .FromJust());
   20708           5 : }
   20709             : 
   20710             : 
   20711       25880 : TEST(DefinePropertyPostDetach) {
   20712           5 :   LocalContext context;
   20713          10 :   v8::HandleScope scope(context->GetIsolate());
   20714           5 :   v8::Local<v8::Object> proxy = context->Global();
   20715             :   v8::Local<v8::Function> define_property =
   20716             :       CompileRun(
   20717             :           "(function() {"
   20718             :           "  Object.defineProperty("
   20719             :           "    this,"
   20720             :           "    1,"
   20721             :           "    { configurable: true, enumerable: true, value: 3 });"
   20722             :           "})")
   20723             :           .As<Function>();
   20724           5 :   context->DetachGlobal();
   20725          15 :   CHECK(define_property->Call(context.local(), proxy, 0, nullptr).IsEmpty());
   20726           5 : }
   20727             : 
   20728             : 
   20729          36 : static void InstallContextId(v8::Local<Context> context, int id) {
   20730             :   Context::Scope scope(context);
   20731         144 :   CHECK(CompileRun("Object.prototype")
   20732             :             .As<Object>()
   20733             :             ->Set(context, v8_str("context_id"),
   20734             :                   v8::Integer::New(context->GetIsolate(), id))
   20735             :             .FromJust());
   20736          36 : }
   20737             : 
   20738             : 
   20739         126 : static void CheckContextId(v8::Local<Object> object, int expected) {
   20740         126 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   20741         504 :   CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
   20742             :                          .ToLocalChecked()
   20743             :                          ->Int32Value(context)
   20744             :                          .FromJust());
   20745         126 : }
   20746             : 
   20747             : 
   20748       25881 : THREADED_TEST(CreationContext) {
   20749           6 :   v8::Isolate* isolate = CcTest::isolate();
   20750           6 :   HandleScope handle_scope(isolate);
   20751           6 :   Local<Context> context1 = Context::New(isolate);
   20752           6 :   InstallContextId(context1, 1);
   20753           6 :   Local<Context> context2 = Context::New(isolate);
   20754           6 :   InstallContextId(context2, 2);
   20755           6 :   Local<Context> context3 = Context::New(isolate);
   20756           6 :   InstallContextId(context3, 3);
   20757             : 
   20758           6 :   Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
   20759             : 
   20760             :   Local<Object> object1;
   20761             :   Local<Function> func1;
   20762             :   {
   20763             :     Context::Scope scope(context1);
   20764           6 :     object1 = Object::New(isolate);
   20765           6 :     func1 = tmpl->GetFunction(context1).ToLocalChecked();
   20766             :   }
   20767             : 
   20768             :   Local<Object> object2;
   20769             :   Local<Function> func2;
   20770             :   {
   20771             :     Context::Scope scope(context2);
   20772           6 :     object2 = Object::New(isolate);
   20773           6 :     func2 = tmpl->GetFunction(context2).ToLocalChecked();
   20774             :   }
   20775             : 
   20776             :   Local<Object> instance1;
   20777             :   Local<Object> instance2;
   20778             : 
   20779             :   {
   20780             :     Context::Scope scope(context3);
   20781             :     instance1 = func1->NewInstance(context3).ToLocalChecked();
   20782             :     instance2 = func2->NewInstance(context3).ToLocalChecked();
   20783             :   }
   20784             : 
   20785             :   {
   20786           6 :     Local<Context> other_context = Context::New(isolate);
   20787             :     Context::Scope scope(other_context);
   20788          12 :     CHECK(object1->CreationContext() == context1);
   20789           6 :     CheckContextId(object1, 1);
   20790          12 :     CHECK(func1->CreationContext() == context1);
   20791           6 :     CheckContextId(func1, 1);
   20792          12 :     CHECK(instance1->CreationContext() == context1);
   20793           6 :     CheckContextId(instance1, 1);
   20794          12 :     CHECK(object2->CreationContext() == context2);
   20795           6 :     CheckContextId(object2, 2);
   20796          12 :     CHECK(func2->CreationContext() == context2);
   20797           6 :     CheckContextId(func2, 2);
   20798          12 :     CHECK(instance2->CreationContext() == context2);
   20799           6 :     CheckContextId(instance2, 2);
   20800             :   }
   20801             : 
   20802             :   {
   20803             :     Context::Scope scope(context1);
   20804          12 :     CHECK(object1->CreationContext() == context1);
   20805           6 :     CheckContextId(object1, 1);
   20806          12 :     CHECK(func1->CreationContext() == context1);
   20807           6 :     CheckContextId(func1, 1);
   20808          12 :     CHECK(instance1->CreationContext() == context1);
   20809           6 :     CheckContextId(instance1, 1);
   20810          12 :     CHECK(object2->CreationContext() == context2);
   20811           6 :     CheckContextId(object2, 2);
   20812          12 :     CHECK(func2->CreationContext() == context2);
   20813           6 :     CheckContextId(func2, 2);
   20814          12 :     CHECK(instance2->CreationContext() == context2);
   20815           6 :     CheckContextId(instance2, 2);
   20816             :   }
   20817             : 
   20818             :   {
   20819             :     Context::Scope scope(context2);
   20820          12 :     CHECK(object1->CreationContext() == context1);
   20821           6 :     CheckContextId(object1, 1);
   20822          12 :     CHECK(func1->CreationContext() == context1);
   20823           6 :     CheckContextId(func1, 1);
   20824          12 :     CHECK(instance1->CreationContext() == context1);
   20825           6 :     CheckContextId(instance1, 1);
   20826          12 :     CHECK(object2->CreationContext() == context2);
   20827           6 :     CheckContextId(object2, 2);
   20828          12 :     CHECK(func2->CreationContext() == context2);
   20829           6 :     CheckContextId(func2, 2);
   20830          12 :     CHECK(instance2->CreationContext() == context2);
   20831           6 :     CheckContextId(instance2, 2);
   20832           6 :   }
   20833           6 : }
   20834             : 
   20835             : 
   20836       25881 : THREADED_TEST(CreationContextOfJsFunction) {
   20837           6 :   HandleScope handle_scope(CcTest::isolate());
   20838           6 :   Local<Context> context = Context::New(CcTest::isolate());
   20839           6 :   InstallContextId(context, 1);
   20840             : 
   20841             :   Local<Object> function;
   20842             :   {
   20843             :     Context::Scope scope(context);
   20844             :     function = CompileRun("function foo() {}; foo").As<Object>();
   20845             :   }
   20846             : 
   20847           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   20848             :   Context::Scope scope(other_context);
   20849          12 :   CHECK(function->CreationContext() == context);
   20850          12 :   CheckContextId(function, 1);
   20851           6 : }
   20852             : 
   20853             : 
   20854       25881 : THREADED_TEST(CreationContextOfJsBoundFunction) {
   20855           6 :   HandleScope handle_scope(CcTest::isolate());
   20856           6 :   Local<Context> context1 = Context::New(CcTest::isolate());
   20857           6 :   InstallContextId(context1, 1);
   20858           6 :   Local<Context> context2 = Context::New(CcTest::isolate());
   20859           6 :   InstallContextId(context2, 2);
   20860             : 
   20861             :   Local<Function> target_function;
   20862             :   {
   20863             :     Context::Scope scope(context1);
   20864             :     target_function = CompileRun("function foo() {}; foo").As<Function>();
   20865             :   }
   20866             : 
   20867             :   Local<Function> bound_function1, bound_function2;
   20868             :   {
   20869             :     Context::Scope scope(context2);
   20870          24 :     CHECK(context2->Global()
   20871             :               ->Set(context2, v8_str("foo"), target_function)
   20872             :               .FromJust());
   20873             :     bound_function1 = CompileRun("foo.bind(1)").As<Function>();
   20874             :     bound_function2 =
   20875             :         CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
   20876             :   }
   20877             : 
   20878           6 :   Local<Context> other_context = Context::New(CcTest::isolate());
   20879             :   Context::Scope scope(other_context);
   20880          12 :   CHECK(bound_function1->CreationContext() == context1);
   20881           6 :   CheckContextId(bound_function1, 1);
   20882          12 :   CHECK(bound_function2->CreationContext() == context1);
   20883          12 :   CheckContextId(bound_function2, 1);
   20884           6 : }
   20885             : 
   20886             : 
   20887          20 : void HasOwnPropertyIndexedPropertyGetter(
   20888             :     uint32_t index,
   20889             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20890          20 :   if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
   20891          20 : }
   20892             : 
   20893             : 
   20894          10 : void HasOwnPropertyNamedPropertyGetter(
   20895             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   20896          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20897          20 :           .FromJust()) {
   20898           5 :     info.GetReturnValue().Set(v8_str("yes"));
   20899             :   }
   20900          10 : }
   20901             : 
   20902             : 
   20903          50 : void HasOwnPropertyIndexedPropertyQuery(
   20904             :     uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20905          50 :   if (index == 42) info.GetReturnValue().Set(1);
   20906          50 : }
   20907             : 
   20908             : 
   20909          10 : void HasOwnPropertyNamedPropertyQuery(
   20910             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20911          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   20912          20 :           .FromJust()) {
   20913             :     info.GetReturnValue().Set(1);
   20914             :   }
   20915          10 : }
   20916             : 
   20917             : 
   20918          10 : void HasOwnPropertyNamedPropertyQuery2(
   20919             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
   20920          30 :   if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
   20921          20 :           .FromJust()) {
   20922             :     info.GetReturnValue().Set(1);
   20923             :   }
   20924          10 : }
   20925             : 
   20926           0 : void HasOwnPropertyAccessorGetter(
   20927             :     Local<String> property,
   20928             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   20929           0 :   info.GetReturnValue().Set(v8_str("yes"));
   20930           0 : }
   20931             : 
   20932           5 : void HasOwnPropertyAccessorNameGetter(
   20933             :     Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
   20934           5 :   info.GetReturnValue().Set(v8_str("yes"));
   20935           5 : }
   20936             : 
   20937       25880 : TEST(HasOwnProperty) {
   20938           5 :   LocalContext env;
   20939           5 :   v8::Isolate* isolate = env->GetIsolate();
   20940          10 :   v8::HandleScope scope(isolate);
   20941             :   { // Check normal properties and defined getters.
   20942             :     Local<Value> value = CompileRun(
   20943             :         "function Foo() {"
   20944             :         "    this.foo = 11;"
   20945             :         "    this.__defineGetter__('baz', function() { return 1; });"
   20946             :         "};"
   20947             :         "function Bar() { "
   20948             :         "    this.bar = 13;"
   20949             :         "    this.__defineGetter__('bla', function() { return 2; });"
   20950             :         "};"
   20951             :         "Bar.prototype = new Foo();"
   20952             :         "new Bar();");
   20953           5 :     CHECK(value->IsObject());
   20954           5 :     Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
   20955          15 :     CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
   20956          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20957          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20958          15 :     CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
   20959          15 :     CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
   20960          15 :     CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
   20961             :   }
   20962             :   { // Check named getter interceptors.
   20963           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20964             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20965           5 :         HasOwnPropertyNamedPropertyGetter));
   20966           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20967          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20968          10 :     CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
   20969          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20970          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20971             :   }
   20972             :   { // Check indexed getter interceptors.
   20973           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20974             :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20975           5 :         HasOwnPropertyIndexedPropertyGetter));
   20976           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20977          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20978          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   20979          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
   20980          10 :     CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
   20981          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20982             :   }
   20983             :   { // Check named query interceptors.
   20984           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20985             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   20986           5 :         nullptr, nullptr, HasOwnPropertyNamedPropertyQuery));
   20987           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20988          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   20989          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   20990             :   }
   20991             :   { // Check indexed query interceptors.
   20992           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   20993             :     templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   20994           5 :         nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   20995           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   20996          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
   20997          10 :     CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
   20998          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
   20999          10 :     CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
   21000             :   }
   21001             :   { // Check callbacks.
   21002           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21003           5 :     templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
   21004           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21005          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21006          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21007             :   }
   21008             :   { // Check that query wins on disagreement.
   21009           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21010             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21011             :         HasOwnPropertyNamedPropertyGetter, nullptr,
   21012           5 :         HasOwnPropertyNamedPropertyQuery2));
   21013           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21014          15 :     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   21015          15 :     CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   21016             :   }
   21017             :   {  // Check that non-internalized keys are handled correctly.
   21018           5 :     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21019             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
   21020           5 :         HasOwnPropertyAccessorNameGetter));
   21021           5 :     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   21022          25 :     env->Global()->Set(env.local(), v8_str("obj"), instance).FromJust();
   21023             :     const char* src =
   21024             :         "var dyn_string = 'this string ';"
   21025             :         "dyn_string += 'does not exist elsewhere';"
   21026             :         "({}).hasOwnProperty.call(obj, dyn_string)";
   21027           5 :     CHECK(CompileRun(src)->BooleanValue(isolate));
   21028           5 :   }
   21029           5 : }
   21030             : 
   21031             : 
   21032       25880 : TEST(IndexedInterceptorWithStringProto) {
   21033           5 :   v8::Isolate* isolate = CcTest::isolate();
   21034           5 :   v8::HandleScope scope(isolate);
   21035           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21036             :   templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
   21037           5 :       nullptr, nullptr, HasOwnPropertyIndexedPropertyQuery));
   21038          10 :   LocalContext context;
   21039          30 :   CHECK(context->Global()
   21040             :             ->Set(context.local(), v8_str("obj"),
   21041             :                   templ->NewInstance(context.local()).ToLocalChecked())
   21042             :             .FromJust());
   21043             :   CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
   21044             :   // These should be intercepted.
   21045           5 :   CHECK(CompileRun("42 in obj")->BooleanValue(isolate));
   21046           5 :   CHECK(CompileRun("'42' in obj")->BooleanValue(isolate));
   21047             :   // These should fall through to the String prototype.
   21048           5 :   CHECK(CompileRun("0 in obj")->BooleanValue(isolate));
   21049           5 :   CHECK(CompileRun("'0' in obj")->BooleanValue(isolate));
   21050             :   // And these should both fail.
   21051           5 :   CHECK(!CompileRun("32 in obj")->BooleanValue(isolate));
   21052          10 :   CHECK(!CompileRun("'32' in obj")->BooleanValue(isolate));
   21053           5 : }
   21054             : 
   21055             : 
   21056          18 : void CheckCodeGenerationAllowed() {
   21057          18 :   Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   21058             :   Local<Value> result = CompileRun("eval('42')");
   21059          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21060             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   21061          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21062             :   result = CompileRun("var f = new Function('return 42'); f()");
   21063          36 :   CHECK_EQ(42, result->Int32Value(context).FromJust());
   21064          18 : }
   21065             : 
   21066             : 
   21067          12 : void CheckCodeGenerationDisallowed() {
   21068          12 :   TryCatch try_catch(CcTest::isolate());
   21069             : 
   21070             :   Local<Value> result = CompileRun("eval('42')");
   21071          12 :   CHECK(result.IsEmpty());
   21072          12 :   CHECK(try_catch.HasCaught());
   21073          12 :   try_catch.Reset();
   21074             : 
   21075             :   result = CompileRun("(function(e) { return e('42'); })(eval)");
   21076          12 :   CHECK(result.IsEmpty());
   21077          12 :   CHECK(try_catch.HasCaught());
   21078          12 :   try_catch.Reset();
   21079             : 
   21080             :   result = CompileRun("var f = new Function('return 42'); f()");
   21081          12 :   CHECK(result.IsEmpty());
   21082          12 :   CHECK(try_catch.HasCaught());
   21083          12 : }
   21084             : 
   21085             : char first_fourty_bytes[41];
   21086             : 
   21087          23 : bool CodeGenerationAllowed(Local<Context> context, Local<String> source) {
   21088          23 :   String::Utf8Value str(CcTest::isolate(), source);
   21089             :   size_t len = std::min(sizeof(first_fourty_bytes) - 1,
   21090          46 :                         static_cast<size_t>(str.length()));
   21091          23 :   strncpy(first_fourty_bytes, *str, len);
   21092          23 :   first_fourty_bytes[len] = 0;
   21093          23 :   ApiTestFuzzer::Fuzz();
   21094          23 :   return true;
   21095             : }
   21096             : 
   21097          23 : bool CodeGenerationDisallowed(Local<Context> context, Local<String> source) {
   21098          23 :   ApiTestFuzzer::Fuzz();
   21099          23 :   return false;
   21100             : }
   21101             : 
   21102             : 
   21103       25881 : THREADED_TEST(AllowCodeGenFromStrings) {
   21104           6 :   LocalContext context;
   21105          12 :   v8::HandleScope scope(context->GetIsolate());
   21106             : 
   21107             :   // eval and the Function constructor allowed by default.
   21108           6 :   CHECK(context->IsCodeGenerationFromStringsAllowed());
   21109           6 :   CheckCodeGenerationAllowed();
   21110             : 
   21111             :   // Disallow eval and the Function constructor.
   21112           6 :   context->AllowCodeGenerationFromStrings(false);
   21113           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21114           6 :   CheckCodeGenerationDisallowed();
   21115             : 
   21116             :   // Allow again.
   21117           6 :   context->AllowCodeGenerationFromStrings(true);
   21118           6 :   CheckCodeGenerationAllowed();
   21119             : 
   21120             :   // Disallow but setting a global callback that will allow the calls.
   21121           6 :   context->AllowCodeGenerationFromStrings(false);
   21122             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21123           6 :       &CodeGenerationAllowed);
   21124           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21125           6 :   CheckCodeGenerationAllowed();
   21126             : 
   21127             :   // Set a callback that disallows the code generation.
   21128             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21129           6 :       &CodeGenerationDisallowed);
   21130           6 :   CHECK(!context->IsCodeGenerationFromStringsAllowed());
   21131          12 :   CheckCodeGenerationDisallowed();
   21132           6 : }
   21133             : 
   21134             : 
   21135       25880 : TEST(SetErrorMessageForCodeGenFromStrings) {
   21136           5 :   LocalContext context;
   21137          10 :   v8::HandleScope scope(context->GetIsolate());
   21138          10 :   TryCatch try_catch(context->GetIsolate());
   21139             : 
   21140           5 :   Local<String> message = v8_str("Message");
   21141           5 :   Local<String> expected_message = v8_str("Uncaught EvalError: Message");
   21142             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21143           5 :       &CodeGenerationDisallowed);
   21144           5 :   context->AllowCodeGenerationFromStrings(false);
   21145           5 :   context->SetErrorMessageForCodeGenerationFromStrings(message);
   21146             :   Local<Value> result = CompileRun("eval('42')");
   21147           5 :   CHECK(result.IsEmpty());
   21148           5 :   CHECK(try_catch.HasCaught());
   21149          10 :   Local<String> actual_message = try_catch.Message()->Get();
   21150          20 :   CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
   21151           5 : }
   21152             : 
   21153       25880 : TEST(CaptureSourceForCodeGenFromStrings) {
   21154           5 :   LocalContext context;
   21155          10 :   v8::HandleScope scope(context->GetIsolate());
   21156          10 :   TryCatch try_catch(context->GetIsolate());
   21157             : 
   21158             :   context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
   21159           5 :       &CodeGenerationAllowed);
   21160           5 :   context->AllowCodeGenerationFromStrings(false);
   21161             :   CompileRun("eval('42')");
   21162          10 :   CHECK(!strcmp(first_fourty_bytes, "42"));
   21163           5 : }
   21164             : 
   21165           6 : static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21166           6 : }
   21167             : 
   21168             : 
   21169       25881 : THREADED_TEST(CallAPIFunctionOnNonObject) {
   21170           6 :   LocalContext context;
   21171           6 :   v8::Isolate* isolate = context->GetIsolate();
   21172          12 :   v8::HandleScope scope(isolate);
   21173             :   Local<FunctionTemplate> templ =
   21174           6 :       v8::FunctionTemplate::New(isolate, NonObjectThis);
   21175             :   Local<Function> function =
   21176          12 :       templ->GetFunction(context.local()).ToLocalChecked();
   21177          30 :   CHECK(context->Global()
   21178             :             ->Set(context.local(), v8_str("f"), function)
   21179             :             .FromJust());
   21180          12 :   TryCatch try_catch(isolate);
   21181           6 :   CompileRun("f.call(2)");
   21182           6 : }
   21183             : 
   21184             : 
   21185             : // Regression test for issue 1470.
   21186       25881 : THREADED_TEST(ReadOnlyIndexedProperties) {
   21187           6 :   v8::Isolate* isolate = CcTest::isolate();
   21188           6 :   v8::HandleScope scope(isolate);
   21189           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   21190             : 
   21191          12 :   LocalContext context;
   21192          12 :   Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   21193          30 :   CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
   21194             :   obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
   21195          24 :                          v8::ReadOnly)
   21196          12 :       .FromJust();
   21197          24 :   obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
   21198          30 :   CHECK(v8_str("DONT_CHANGE")
   21199             :             ->Equals(context.local(),
   21200             :                      obj->Get(context.local(), v8_str("1")).ToLocalChecked())
   21201             :             .FromJust());
   21202             :   obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
   21203          24 :                          v8::ReadOnly)
   21204          12 :       .FromJust();
   21205          18 :   obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
   21206          24 :   CHECK(v8_str("DONT_CHANGE")
   21207             :             ->Equals(context.local(),
   21208             :                      obj->Get(context.local(), v8_num(2)).ToLocalChecked())
   21209             :             .FromJust());
   21210             : 
   21211             :   // Test non-smi case.
   21212             :   obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
   21213          24 :                          v8_str("DONT_CHANGE"), v8::ReadOnly)
   21214          12 :       .FromJust();
   21215          24 :   obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
   21216          30 :   CHECK(v8_str("DONT_CHANGE")
   21217             :             ->Equals(context.local(),
   21218             :                      obj->Get(context.local(), v8_str("2000000000"))
   21219             :                          .ToLocalChecked())
   21220           6 :             .FromJust());
   21221           6 : }
   21222             : 
   21223          12 : static int CountLiveMapsInMapCache(i::Context context) {
   21224          24 :   i::WeakFixedArray map_cache = i::WeakFixedArray::cast(context->map_cache());
   21225             :   int length = map_cache->length();
   21226             :   int count = 0;
   21227        1548 :   for (int i = 0; i < length; i++) {
   21228        3072 :     if (map_cache->Get(i)->IsWeak()) count++;
   21229             :   }
   21230          12 :   return count;
   21231             : }
   21232             : 
   21233             : 
   21234       25881 : THREADED_TEST(Regress1516) {
   21235           6 :   LocalContext context;
   21236          12 :   v8::HandleScope scope(context->GetIsolate());
   21237             : 
   21238             :   // Object with 20 properties is not a common case, so it should be removed
   21239             :   // from the cache after GC.
   21240           6 :   { v8::HandleScope temp_scope(context->GetIsolate());
   21241             :     CompileRun(
   21242             :         "({"
   21243             :         "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
   21244             :         "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
   21245             :         "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
   21246             :         "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
   21247           6 :         "})");
   21248             :   }
   21249             : 
   21250           6 :   int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
   21251           6 :   CHECK_LE(1, elements);
   21252             : 
   21253             :   // We have to abort incremental marking here to abandon black pages.
   21254           6 :   CcTest::PreciseCollectAllGarbage();
   21255             : 
   21256          12 :   CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
   21257           6 : }
   21258             : 
   21259             : 
   21260          84 : static void TestReceiver(Local<Value> expected_result,
   21261             :                          Local<Value> expected_receiver,
   21262             :                          const char* code) {
   21263             :   Local<Value> result = CompileRun(code);
   21264          84 :   Local<Context> context = CcTest::isolate()->GetCurrentContext();
   21265          84 :   CHECK(result->IsObject());
   21266         252 :   CHECK(expected_receiver
   21267             :             ->Equals(context,
   21268             :                      result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
   21269             :             .FromJust());
   21270         252 :   CHECK(expected_result
   21271             :             ->Equals(context,
   21272             :                      result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
   21273             :             .FromJust());
   21274          84 : }
   21275             : 
   21276             : 
   21277       25881 : THREADED_TEST(ForeignFunctionReceiver) {
   21278           6 :   v8::Isolate* isolate = CcTest::isolate();
   21279           6 :   HandleScope scope(isolate);
   21280             : 
   21281             :   // Create two contexts with different "id" properties ('i' and 'o').
   21282             :   // Call a function both from its own context and from a the foreign
   21283             :   // context, and see what "this" is bound to (returning both "this"
   21284             :   // and "this.id" for comparison).
   21285             : 
   21286           6 :   Local<Context> foreign_context = v8::Context::New(isolate);
   21287           6 :   foreign_context->Enter();
   21288             :   Local<Value> foreign_function =
   21289             :     CompileRun("function func() { return { 0: this.id, "
   21290             :                "                           1: this, "
   21291             :                "                           toString: function() { "
   21292             :                "                               return this[0];"
   21293             :                "                           }"
   21294             :                "                         };"
   21295             :                "}"
   21296             :                "var id = 'i';"
   21297             :                "func;");
   21298           6 :   CHECK(foreign_function->IsFunction());
   21299           6 :   foreign_context->Exit();
   21300             : 
   21301          12 :   LocalContext context;
   21302             : 
   21303           6 :   Local<String> password = v8_str("Password");
   21304             :   // Don't get hit by security checks when accessing foreign_context's
   21305             :   // global receiver (aka. global proxy).
   21306           6 :   context->SetSecurityToken(password);
   21307           6 :   foreign_context->SetSecurityToken(password);
   21308             : 
   21309           6 :   Local<String> i = v8_str("i");
   21310           6 :   Local<String> o = v8_str("o");
   21311           6 :   Local<String> id = v8_str("id");
   21312             : 
   21313             :   CompileRun("function ownfunc() { return { 0: this.id, "
   21314             :              "                              1: this, "
   21315             :              "                              toString: function() { "
   21316             :              "                                  return this[0];"
   21317             :              "                              }"
   21318             :              "                             };"
   21319             :              "}"
   21320             :              "var id = 'o';"
   21321             :              "ownfunc");
   21322          30 :   CHECK(context->Global()
   21323             :             ->Set(context.local(), v8_str("func"), foreign_function)
   21324             :             .FromJust());
   21325             : 
   21326             :   // Sanity check the contexts.
   21327          24 :   CHECK(
   21328             :       i->Equals(
   21329             :            context.local(),
   21330             :            foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
   21331             :           .FromJust());
   21332          30 :   CHECK(o->Equals(context.local(),
   21333             :                   context->Global()->Get(context.local(), id).ToLocalChecked())
   21334             :             .FromJust());
   21335             : 
   21336             :   // Checking local function's receiver.
   21337             :   // Calling function using its call/apply methods.
   21338          12 :   TestReceiver(o, context->Global(), "ownfunc.call()");
   21339          12 :   TestReceiver(o, context->Global(), "ownfunc.apply()");
   21340             :   // Making calls through built-in functions.
   21341          12 :   TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
   21342          12 :   CHECK(
   21343             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
   21344             :           .FromJust());
   21345          12 :   CHECK(
   21346             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
   21347             :           .FromJust());
   21348          12 :   CHECK(
   21349             :       o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
   21350             :           .FromJust());
   21351             :   // Calling with environment record as base.
   21352          12 :   TestReceiver(o, context->Global(), "ownfunc()");
   21353             :   // Calling with no base.
   21354          12 :   TestReceiver(o, context->Global(), "(1,ownfunc)()");
   21355             : 
   21356             :   // Checking foreign function return value.
   21357             :   // Calling function using its call/apply methods.
   21358          12 :   TestReceiver(i, foreign_context->Global(), "func.call()");
   21359          12 :   TestReceiver(i, foreign_context->Global(), "func.apply()");
   21360             :   // Calling function using another context's call/apply methods.
   21361             :   TestReceiver(i, foreign_context->Global(),
   21362          12 :                "Function.prototype.call.call(func)");
   21363             :   TestReceiver(i, foreign_context->Global(),
   21364          12 :                "Function.prototype.call.apply(func)");
   21365             :   TestReceiver(i, foreign_context->Global(),
   21366          12 :                "Function.prototype.apply.call(func)");
   21367             :   TestReceiver(i, foreign_context->Global(),
   21368          12 :                "Function.prototype.apply.apply(func)");
   21369             :   // Making calls through built-in functions.
   21370          12 :   TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
   21371             :   // ToString(func()) is func()[0], i.e., the returned this.id.
   21372          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
   21373             :             .FromJust());
   21374          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
   21375             :             .FromJust());
   21376          12 :   CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
   21377             :             .FromJust());
   21378             : 
   21379             :   // Calling with environment record as base.
   21380          12 :   TestReceiver(i, foreign_context->Global(), "func()");
   21381             :   // Calling with no base.
   21382          18 :   TestReceiver(i, foreign_context->Global(), "(1,func)()");
   21383           6 : }
   21384             : 
   21385             : 
   21386             : uint8_t callback_fired = 0;
   21387             : uint8_t before_call_entered_callback_count1 = 0;
   21388             : uint8_t before_call_entered_callback_count2 = 0;
   21389             : 
   21390             : 
   21391           5 : void CallCompletedCallback1(v8::Isolate*) {
   21392           5 :   v8::base::OS::Print("Firing callback 1.\n");
   21393           5 :   callback_fired ^= 1;  // Toggle first bit.
   21394           5 : }
   21395             : 
   21396             : 
   21397          15 : void CallCompletedCallback2(v8::Isolate*) {
   21398          15 :   v8::base::OS::Print("Firing callback 2.\n");
   21399          15 :   callback_fired ^= 2;  // Toggle second bit.
   21400          15 : }
   21401             : 
   21402             : 
   21403          20 : void BeforeCallEnteredCallback1(v8::Isolate*) {
   21404          20 :   v8::base::OS::Print("Firing before call entered callback 1.\n");
   21405          20 :   before_call_entered_callback_count1++;
   21406          20 : }
   21407             : 
   21408             : 
   21409          60 : void BeforeCallEnteredCallback2(v8::Isolate*) {
   21410          60 :   v8::base::OS::Print("Firing before call entered callback 2.\n");
   21411          60 :   before_call_entered_callback_count2++;
   21412          60 : }
   21413             : 
   21414             : 
   21415          60 : void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
   21416             :   int32_t level =
   21417         180 :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
   21418          60 :   if (level < 3) {
   21419          45 :     level++;
   21420          45 :     v8::base::OS::Print("Entering recursion level %d.\n", level);
   21421             :     char script[64];
   21422             :     i::Vector<char> script_vector(script, sizeof(script));
   21423          45 :     i::SNPrintF(script_vector, "recursion(%d)", level);
   21424             :     CompileRun(script_vector.start());
   21425          45 :     v8::base::OS::Print("Leaving recursion level %d.\n", level);
   21426          90 :     CHECK_EQ(0, callback_fired);
   21427             :   } else {
   21428          15 :     v8::base::OS::Print("Recursion ends.\n");
   21429          30 :     CHECK_EQ(0, callback_fired);
   21430             :   }
   21431          60 : }
   21432             : 
   21433             : 
   21434       25880 : TEST(CallCompletedCallback) {
   21435           5 :   LocalContext env;
   21436          10 :   v8::HandleScope scope(env->GetIsolate());
   21437             :   v8::Local<v8::FunctionTemplate> recursive_runtime =
   21438           5 :       v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
   21439             :   env->Global()
   21440             :       ->Set(env.local(), v8_str("recursion"),
   21441          30 :             recursive_runtime->GetFunction(env.local()).ToLocalChecked())
   21442          10 :       .FromJust();
   21443             :   // Adding the same callback a second time has no effect.
   21444           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21445           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
   21446           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
   21447           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21448           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
   21449           5 :   env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
   21450           5 :   v8::base::OS::Print("--- Script (1) ---\n");
   21451           5 :   callback_fired = 0;
   21452           5 :   before_call_entered_callback_count1 = 0;
   21453           5 :   before_call_entered_callback_count2 = 0;
   21454             :   Local<Script> script =
   21455           5 :       v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
   21456           5 :   script->Run(env.local()).ToLocalChecked();
   21457          10 :   CHECK_EQ(3, callback_fired);
   21458          10 :   CHECK_EQ(4, before_call_entered_callback_count1);
   21459          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21460             : 
   21461           5 :   v8::base::OS::Print("\n--- Script (2) ---\n");
   21462           5 :   callback_fired = 0;
   21463           5 :   before_call_entered_callback_count1 = 0;
   21464           5 :   before_call_entered_callback_count2 = 0;
   21465           5 :   env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
   21466             :   env->GetIsolate()->RemoveBeforeCallEnteredCallback(
   21467           5 :       BeforeCallEnteredCallback1);
   21468           5 :   script->Run(env.local()).ToLocalChecked();
   21469          10 :   CHECK_EQ(2, callback_fired);
   21470          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   21471          10 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21472             : 
   21473           5 :   v8::base::OS::Print("\n--- Function ---\n");
   21474           5 :   callback_fired = 0;
   21475           5 :   before_call_entered_callback_count1 = 0;
   21476           5 :   before_call_entered_callback_count2 = 0;
   21477             :   Local<Function> recursive_function = Local<Function>::Cast(
   21478          25 :       env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
   21479           5 :   v8::Local<Value> args[] = {v8_num(0)};
   21480          15 :   recursive_function->Call(env.local(), env->Global(), 1, args)
   21481           5 :       .ToLocalChecked();
   21482          10 :   CHECK_EQ(2, callback_fired);
   21483          10 :   CHECK_EQ(0, before_call_entered_callback_count1);
   21484          15 :   CHECK_EQ(4, before_call_entered_callback_count2);
   21485           5 : }
   21486             : 
   21487             : 
   21488           5 : void CallCompletedCallbackNoException(v8::Isolate*) {
   21489           5 :   v8::HandleScope scope(CcTest::isolate());
   21490           5 :   CompileRun("1+1;");
   21491           5 : }
   21492             : 
   21493             : 
   21494           5 : void CallCompletedCallbackException(v8::Isolate*) {
   21495           5 :   v8::HandleScope scope(CcTest::isolate());
   21496           5 :   CompileRun("throw 'second exception';");
   21497           5 : }
   21498             : 
   21499             : 
   21500       25880 : TEST(CallCompletedCallbackOneException) {
   21501           5 :   LocalContext env;
   21502          10 :   v8::HandleScope scope(env->GetIsolate());
   21503           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
   21504           5 :   CompileRun("throw 'exception';");
   21505           5 : }
   21506             : 
   21507             : 
   21508       25880 : TEST(CallCompletedCallbackTwoExceptions) {
   21509           5 :   LocalContext env;
   21510          10 :   v8::HandleScope scope(env->GetIsolate());
   21511           5 :   env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
   21512           5 :   CompileRun("throw 'first exception';");
   21513           5 : }
   21514             : 
   21515             : 
   21516         135 : static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
   21517          45 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21518          45 :   v8::HandleScope scope(info.GetIsolate());
   21519             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21520          90 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21521          45 :   CompileRun("ext1Calls++;");
   21522          45 : }
   21523             : 
   21524             : 
   21525         150 : static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
   21526          50 :   CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   21527          50 :   v8::HandleScope scope(info.GetIsolate());
   21528             :   v8::MicrotasksScope microtasks(info.GetIsolate(),
   21529         100 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21530          50 :   CompileRun("ext2Calls++;");
   21531          50 : }
   21532             : 
   21533             : void* g_passed_to_three = nullptr;
   21534             : 
   21535          10 : static void MicrotaskThree(void* data) {
   21536          10 :   g_passed_to_three = data;
   21537          10 : }
   21538             : 
   21539             : 
   21540       25880 : TEST(EnqueueMicrotask) {
   21541           5 :   LocalContext env;
   21542          10 :   v8::HandleScope scope(env->GetIsolate());
   21543           5 :   CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
   21544             :   CompileRun(
   21545             :       "var ext1Calls = 0;"
   21546             :       "var ext2Calls = 0;");
   21547             :   CompileRun("1+1;");
   21548          15 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21549          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21550             : 
   21551             :   env->GetIsolate()->EnqueueMicrotask(
   21552          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21553             :   CompileRun("1+1;");
   21554          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21555          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21556             : 
   21557             :   env->GetIsolate()->EnqueueMicrotask(
   21558          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21559             :   env->GetIsolate()->EnqueueMicrotask(
   21560          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21561             :   CompileRun("1+1;");
   21562          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21563          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21564             : 
   21565             :   env->GetIsolate()->EnqueueMicrotask(
   21566          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21567             :   CompileRun("1+1;");
   21568          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21569          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21570             : 
   21571             :   CompileRun("1+1;");
   21572          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21573          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21574             : 
   21575           5 :   g_passed_to_three = nullptr;
   21576           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
   21577             :   CompileRun("1+1;");
   21578           5 :   CHECK(!g_passed_to_three);
   21579          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21580          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21581             : 
   21582             :   int dummy;
   21583             :   env->GetIsolate()->EnqueueMicrotask(
   21584          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21585           5 :   env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
   21586             :   env->GetIsolate()->EnqueueMicrotask(
   21587          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21588             :   CompileRun("1+1;");
   21589           5 :   CHECK_EQ(&dummy, g_passed_to_three);
   21590          15 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21591          15 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21592          10 :   g_passed_to_three = nullptr;
   21593           5 : }
   21594             : 
   21595             : 
   21596           5 : static void MicrotaskExceptionOne(
   21597          10 :     const v8::FunctionCallbackInfo<Value>& info) {
   21598           5 :   v8::HandleScope scope(info.GetIsolate());
   21599             :   CompileRun("exception1Calls++;");
   21600             :   info.GetIsolate()->ThrowException(
   21601          10 :       v8::Exception::Error(v8_str("first")));
   21602           5 : }
   21603             : 
   21604             : 
   21605           5 : static void MicrotaskExceptionTwo(
   21606          10 :     const v8::FunctionCallbackInfo<Value>& info) {
   21607           5 :   v8::HandleScope scope(info.GetIsolate());
   21608             :   CompileRun("exception2Calls++;");
   21609             :   info.GetIsolate()->ThrowException(
   21610          10 :       v8::Exception::Error(v8_str("second")));
   21611           5 : }
   21612             : 
   21613             : 
   21614       25880 : TEST(RunMicrotasksIgnoresThrownExceptions) {
   21615           5 :   LocalContext env;
   21616           5 :   v8::Isolate* isolate = env->GetIsolate();
   21617          10 :   v8::HandleScope scope(isolate);
   21618             :   CompileRun(
   21619             :       "var exception1Calls = 0;"
   21620             :       "var exception2Calls = 0;");
   21621             :   isolate->EnqueueMicrotask(
   21622          10 :       Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
   21623             :   isolate->EnqueueMicrotask(
   21624          10 :       Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
   21625          10 :   TryCatch try_catch(isolate);
   21626             :   CompileRun("1+1;");
   21627           5 :   CHECK(!try_catch.HasCaught());
   21628          15 :   CHECK_EQ(1,
   21629             :            CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
   21630          15 :   CHECK_EQ(1,
   21631           5 :            CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
   21632           5 : }
   21633             : 
   21634           5 : static void ThrowExceptionMicrotask(void* data) {
   21635          10 :   CcTest::isolate()->ThrowException(v8_str("exception"));
   21636           5 : }
   21637             : 
   21638             : int microtask_callback_count = 0;
   21639             : 
   21640           5 : static void IncrementCounterMicrotask(void* data) {
   21641           5 :   microtask_callback_count++;
   21642           5 : }
   21643             : 
   21644       25880 : TEST(RunMicrotasksIgnoresThrownExceptionsFromApi) {
   21645           5 :   LocalContext env;
   21646           5 :   v8::Isolate* isolate = CcTest::isolate();
   21647           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21648          10 :   v8::HandleScope scope(isolate);
   21649          10 :   v8::TryCatch try_catch(isolate);
   21650             :   {
   21651           5 :     CHECK(!isolate->IsExecutionTerminating());
   21652           5 :     isolate->EnqueueMicrotask(ThrowExceptionMicrotask);
   21653           5 :     isolate->EnqueueMicrotask(IncrementCounterMicrotask);
   21654           5 :     isolate->RunMicrotasks();
   21655           5 :     CHECK_EQ(1, microtask_callback_count);
   21656           5 :     CHECK(!try_catch.HasCaught());
   21657           5 :   }
   21658           5 : }
   21659             : 
   21660             : uint8_t microtasks_completed_callback_count = 0;
   21661             : 
   21662             : 
   21663          25 : static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
   21664          25 :   ++microtasks_completed_callback_count;
   21665          25 : }
   21666             : 
   21667             : 
   21668       25880 : TEST(SetAutorunMicrotasks) {
   21669           5 :   LocalContext env;
   21670          10 :   v8::HandleScope scope(env->GetIsolate());
   21671             :   env->GetIsolate()->AddMicrotasksCompletedCallback(
   21672           5 :       &MicrotasksCompletedCallback);
   21673             :   CompileRun(
   21674             :       "var ext1Calls = 0;"
   21675             :       "var ext2Calls = 0;");
   21676             :   CompileRun("1+1;");
   21677          15 :   CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21678          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21679           5 :   CHECK_EQ(0u, microtasks_completed_callback_count);
   21680             : 
   21681             :   env->GetIsolate()->EnqueueMicrotask(
   21682          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21683             :   CompileRun("1+1;");
   21684          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21685          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21686           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   21687             : 
   21688           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21689             :   env->GetIsolate()->EnqueueMicrotask(
   21690          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21691             :   env->GetIsolate()->EnqueueMicrotask(
   21692          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21693             :   CompileRun("1+1;");
   21694          15 :   CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21695          15 :   CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21696           5 :   CHECK_EQ(1u, microtasks_completed_callback_count);
   21697             : 
   21698           5 :   env->GetIsolate()->RunMicrotasks();
   21699          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21700          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21701           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   21702             : 
   21703             :   env->GetIsolate()->EnqueueMicrotask(
   21704          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21705             :   CompileRun("1+1;");
   21706          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21707          15 :   CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21708           5 :   CHECK_EQ(2u, microtasks_completed_callback_count);
   21709             : 
   21710           5 :   env->GetIsolate()->RunMicrotasks();
   21711          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21712          15 :   CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21713           5 :   CHECK_EQ(3u, microtasks_completed_callback_count);
   21714             : 
   21715           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21716             :   env->GetIsolate()->EnqueueMicrotask(
   21717          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21718             :   CompileRun("1+1;");
   21719          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21720          15 :   CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21721           5 :   CHECK_EQ(4u, microtasks_completed_callback_count);
   21722             : 
   21723             :   env->GetIsolate()->EnqueueMicrotask(
   21724          10 :       Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21725             :   {
   21726           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
   21727             :     CompileRun("1+1;");
   21728          15 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21729          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21730           5 :     CHECK_EQ(4u, microtasks_completed_callback_count);
   21731             :   }
   21732             : 
   21733             :   CompileRun("1+1;");
   21734          15 :   CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21735          15 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21736           5 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   21737             : 
   21738             :   env->GetIsolate()->RemoveMicrotasksCompletedCallback(
   21739           5 :       &MicrotasksCompletedCallback);
   21740             :   env->GetIsolate()->EnqueueMicrotask(
   21741          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21742             :   CompileRun("1+1;");
   21743          15 :   CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21744          15 :   CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21745          10 :   CHECK_EQ(5u, microtasks_completed_callback_count);
   21746           5 : }
   21747             : 
   21748             : 
   21749       25880 : TEST(RunMicrotasksWithoutEnteringContext) {
   21750           5 :   v8::Isolate* isolate = CcTest::isolate();
   21751           5 :   HandleScope handle_scope(isolate);
   21752           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   21753           5 :   Local<Context> context = Context::New(isolate);
   21754             :   {
   21755             :     Context::Scope context_scope(context);
   21756             :     CompileRun("var ext1Calls = 0;");
   21757             :     isolate->EnqueueMicrotask(
   21758          10 :         Function::New(context, MicrotaskOne).ToLocalChecked());
   21759             :   }
   21760           5 :   isolate->RunMicrotasks();
   21761             :   {
   21762             :     Context::Scope context_scope(context);
   21763          10 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
   21764             :   }
   21765           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21766           5 : }
   21767             : 
   21768           6 : static void Regress808911_MicrotaskCallback(void* data) {
   21769             :   // So here we expect "current context" to be context1 and
   21770             :   // "entered or microtask context" to be context2.
   21771             :   v8::Isolate* isolate = static_cast<v8::Isolate*>(data);
   21772          12 :   CHECK(isolate->GetCurrentContext() !=
   21773             :         isolate->GetEnteredOrMicrotaskContext());
   21774           6 : }
   21775             : 
   21776           6 : static void Regress808911_CurrentContextWrapper(
   21777           6 :     const v8::FunctionCallbackInfo<Value>& info) {
   21778             :   // So here we expect "current context" to be context1 and
   21779             :   // "entered or microtask context" to be context2.
   21780             :   v8::Isolate* isolate = info.GetIsolate();
   21781          12 :   CHECK(isolate->GetCurrentContext() !=
   21782             :         isolate->GetEnteredOrMicrotaskContext());
   21783           6 :   isolate->EnqueueMicrotask(Regress808911_MicrotaskCallback, isolate);
   21784           6 :   isolate->RunMicrotasks();
   21785           6 : }
   21786             : 
   21787       25881 : THREADED_TEST(Regress808911) {
   21788           6 :   v8::Isolate* isolate = CcTest::isolate();
   21789           6 :   HandleScope handle_scope(isolate);
   21790           6 :   Local<Context> context1 = Context::New(isolate);
   21791             :   Local<Function> function;
   21792             :   {
   21793             :     Context::Scope context_scope(context1);
   21794           6 :     function = Function::New(context1, Regress808911_CurrentContextWrapper)
   21795           6 :                    .ToLocalChecked();
   21796             :   }
   21797           6 :   Local<Context> context2 = Context::New(isolate);
   21798             :   Context::Scope context_scope(context2);
   21799           6 :   function->CallAsFunction(context2, v8::Undefined(isolate), 0, nullptr)
   21800          12 :       .ToLocalChecked();
   21801           6 : }
   21802             : 
   21803       25880 : TEST(ScopedMicrotasks) {
   21804           5 :   LocalContext env;
   21805          10 :   v8::HandleScope handles(env->GetIsolate());
   21806           5 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
   21807             :   {
   21808             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   21809           5 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21810             :     env->GetIsolate()->EnqueueMicrotask(
   21811          10 :         Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21812             :     CompileRun(
   21813             :         "var ext1Calls = 0;"
   21814             :         "var ext2Calls = 0;");
   21815             :     CompileRun("1+1;");
   21816          15 :     CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21817          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21818             :     {
   21819             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   21820           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   21821             :       CompileRun("1+1;");
   21822          15 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21823          15 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21824             :       {
   21825             :         v8::MicrotasksScope scope3(env->GetIsolate(),
   21826           5 :                                    v8::MicrotasksScope::kRunMicrotasks);
   21827             :         CompileRun("1+1;");
   21828          15 :         CHECK_EQ(0,
   21829             :                  CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21830          15 :         CHECK_EQ(0,
   21831           5 :                  CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21832             :       }
   21833          15 :       CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21834          15 :       CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21835             :     }
   21836          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21837          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21838             :     env->GetIsolate()->EnqueueMicrotask(
   21839          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21840             :   }
   21841             : 
   21842             :   {
   21843             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21844           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21845          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21846          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21847             :   }
   21848             : 
   21849             :   {
   21850             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   21851           5 :                                v8::MicrotasksScope::kRunMicrotasks);
   21852             :     CompileRun("1+1;");
   21853          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21854          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21855             :     {
   21856             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   21857           5 :                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
   21858             :     }
   21859          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21860          15 :     CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21861             :   }
   21862             : 
   21863             :   {
   21864             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21865           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21866          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21867          15 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21868             :     env->GetIsolate()->EnqueueMicrotask(
   21869          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21870             :   }
   21871             : 
   21872             :   {
   21873           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   21874             :     {
   21875             :       v8::MicrotasksScope scope2(env->GetIsolate(),
   21876           5 :                                  v8::MicrotasksScope::kRunMicrotasks);
   21877             :     }
   21878             :     v8::MicrotasksScope scope3(env->GetIsolate(),
   21879          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21880          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21881          20 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21882             :   }
   21883             : 
   21884             :   {
   21885             :     v8::MicrotasksScope scope1(env->GetIsolate(),
   21886           5 :                                v8::MicrotasksScope::kRunMicrotasks);
   21887           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21888          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21889          15 :     CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21890             :   }
   21891             : 
   21892             :   {
   21893             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21894           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21895          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21896          15 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21897             :   }
   21898             : 
   21899           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21900             : 
   21901             :   {
   21902             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21903           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21904          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21905          15 :     CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21906             :     env->GetIsolate()->EnqueueMicrotask(
   21907          10 :         Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
   21908             :   }
   21909             : 
   21910           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21911             : 
   21912             :   {
   21913             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21914           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21915          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21916          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21917             :   }
   21918             : 
   21919             :   env->GetIsolate()->EnqueueMicrotask(
   21920          10 :       Function::New(env.local(), MicrotaskOne).ToLocalChecked());
   21921             :   {
   21922           5 :     v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
   21923           5 :     v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21924             :     v8::MicrotasksScope scope2(env->GetIsolate(),
   21925          10 :                                v8::MicrotasksScope::kDoNotRunMicrotasks);
   21926          15 :     CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21927          20 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21928             :   }
   21929             : 
   21930           5 :   v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
   21931             : 
   21932             :   {
   21933             :     v8::MicrotasksScope scope(env->GetIsolate(),
   21934           5 :                               v8::MicrotasksScope::kDoNotRunMicrotasks);
   21935          15 :     CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
   21936          15 :     CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
   21937             :   }
   21938             : 
   21939          10 :   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
   21940           5 : }
   21941             : 
   21942             : namespace {
   21943             : 
   21944          35 : void AssertCowElements(bool expected, const char* source) {
   21945             :   Local<Value> object = CompileRun(source);
   21946             :   i::Handle<i::JSObject> array =
   21947          35 :       i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*object.As<Object>()));
   21948          35 :   CHECK_EQ(expected, array->elements()->IsCowArray());
   21949          35 : }
   21950             : 
   21951             : }  // namespace
   21952             : 
   21953       25880 : TEST(CheckCOWArraysCreatedRuntimeCounter) {
   21954           5 :   LocalContext env;
   21955          10 :   v8::HandleScope scope(env->GetIsolate());
   21956           5 :   AssertCowElements(true, "[1, 2, 3]");
   21957           5 :   AssertCowElements(false, "[[1], 2, 3]");
   21958           5 :   AssertCowElements(true, "[[1], 2, 3][0]");
   21959           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.foo)");
   21960           5 :   AssertCowElements(true, "({foo: [4, 5, 6], bar: [3, 0]}.bar)");
   21961           5 :   AssertCowElements(false, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo)");
   21962          10 :   AssertCowElements(true, "({foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'}.foo[3])");
   21963           5 : }
   21964             : 
   21965             : 
   21966       25880 : TEST(StaticGetters) {
   21967           5 :   LocalContext context;
   21968             :   i::Factory* factory = CcTest::i_isolate()->factory();
   21969           5 :   v8::Isolate* isolate = CcTest::isolate();
   21970          10 :   v8::HandleScope scope(isolate);
   21971             :   i::Handle<i::Object> undefined_value = factory->undefined_value();
   21972           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
   21973             :   i::Handle<i::Object> null_value = factory->null_value();
   21974           5 :   CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
   21975             :   i::Handle<i::Object> true_value = factory->true_value();
   21976           5 :   CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
   21977             :   i::Handle<i::Object> false_value = factory->false_value();
   21978          10 :   CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
   21979           5 : }
   21980             : 
   21981             : 
   21982       25880 : UNINITIALIZED_TEST(IsolateEmbedderData) {
   21983           5 :   CcTest::DisableAutomaticDispose();
   21984             :   v8::Isolate::CreateParams create_params;
   21985           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   21986           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   21987           5 :   isolate->Enter();
   21988             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   21989          25 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21990          20 :     CHECK(!isolate->GetData(slot));
   21991          20 :     CHECK(!i_isolate->GetData(slot));
   21992             :   }
   21993          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21994          20 :     void* data = reinterpret_cast<void*>(0xACCE55ED + slot);
   21995             :     isolate->SetData(slot, data);
   21996             :   }
   21997          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   21998          20 :     void* data = reinterpret_cast<void*>(0xACCE55ED + slot);
   21999          20 :     CHECK_EQ(data, isolate->GetData(slot));
   22000          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   22001             :   }
   22002          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22003          20 :     void* data = reinterpret_cast<void*>(0xDECEA5ED + slot);
   22004             :     isolate->SetData(slot, data);
   22005             :   }
   22006          20 :   for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
   22007          20 :     void* data = reinterpret_cast<void*>(0xDECEA5ED + slot);
   22008          20 :     CHECK_EQ(data, isolate->GetData(slot));
   22009          20 :     CHECK_EQ(data, i_isolate->GetData(slot));
   22010             :   }
   22011           5 :   isolate->Exit();
   22012           5 :   isolate->Dispose();
   22013           5 : }
   22014             : 
   22015             : 
   22016       25880 : TEST(StringEmpty) {
   22017           5 :   LocalContext context;
   22018             :   i::Factory* factory = CcTest::i_isolate()->factory();
   22019           5 :   v8::Isolate* isolate = CcTest::isolate();
   22020          10 :   v8::HandleScope scope(isolate);
   22021             :   i::Handle<i::Object> empty_string = factory->empty_string();
   22022          10 :   CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
   22023           5 : }
   22024             : 
   22025             : 
   22026             : static int instance_checked_getter_count = 0;
   22027         120 : static void InstanceCheckedGetter(
   22028             :     Local<String> name,
   22029             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
   22030         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   22031             :             .FromJust());
   22032         120 :   instance_checked_getter_count++;
   22033         120 :   info.GetReturnValue().Set(v8_num(11));
   22034         120 : }
   22035             : 
   22036             : 
   22037             : static int instance_checked_setter_count = 0;
   22038         120 : static void InstanceCheckedSetter(Local<String> name,
   22039             :                       Local<Value> value,
   22040             :                       const v8::PropertyCallbackInfo<void>& info) {
   22041         480 :   CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
   22042             :             .FromJust());
   22043         480 :   CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
   22044             :             .FromJust());
   22045         120 :   instance_checked_setter_count++;
   22046         120 : }
   22047             : 
   22048             : 
   22049         420 : static void CheckInstanceCheckedResult(int getters, int setters,
   22050             :                                        bool expects_callbacks,
   22051             :                                        TryCatch* try_catch) {
   22052         420 :   if (expects_callbacks) {
   22053         240 :     CHECK(!try_catch->HasCaught());
   22054         240 :     CHECK_EQ(getters, instance_checked_getter_count);
   22055         240 :     CHECK_EQ(setters, instance_checked_setter_count);
   22056             :   } else {
   22057         180 :     CHECK(try_catch->HasCaught());
   22058         180 :     CHECK_EQ(0, instance_checked_getter_count);
   22059         180 :     CHECK_EQ(0, instance_checked_setter_count);
   22060             :   }
   22061         420 :   try_catch->Reset();
   22062         420 : }
   22063             : 
   22064             : 
   22065          42 : static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
   22066          42 :   instance_checked_getter_count = 0;
   22067          42 :   instance_checked_setter_count = 0;
   22068          42 :   TryCatch try_catch(CcTest::isolate());
   22069             : 
   22070             :   // Test path through generic runtime code.
   22071             :   CompileRun("obj.foo");
   22072          42 :   CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
   22073             :   CompileRun("obj.foo = 23");
   22074          42 :   CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
   22075             : 
   22076             :   // Test path through generated LoadIC and StoredIC.
   22077             :   CompileRun("function test_get(o) { o.foo; }"
   22078             :              "test_get(obj);");
   22079          42 :   CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
   22080             :   CompileRun("test_get(obj);");
   22081          42 :   CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
   22082             :   CompileRun("test_get(obj);");
   22083          42 :   CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
   22084             :   CompileRun("function test_set(o) { o.foo = 23; }"
   22085             :              "test_set(obj);");
   22086          42 :   CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
   22087             :   CompileRun("test_set(obj);");
   22088          42 :   CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
   22089             :   CompileRun("test_set(obj);");
   22090          42 :   CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
   22091             : 
   22092             :   // Test path through optimized code.
   22093             :   CompileRun("%OptimizeFunctionOnNextCall(test_get);"
   22094             :              "test_get(obj);");
   22095          42 :   CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
   22096             :   CompileRun("%OptimizeFunctionOnNextCall(test_set);"
   22097             :              "test_set(obj);");
   22098          42 :   CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
   22099             : 
   22100             :   // Cleanup so that closures start out fresh in next check.
   22101             :   CompileRun(
   22102             :       "%DeoptimizeFunction(test_get);"
   22103             :       "%ClearFunctionFeedback(test_get);"
   22104             :       "%DeoptimizeFunction(test_set);"
   22105          42 :       "%ClearFunctionFeedback(test_set);");
   22106          42 : }
   22107             : 
   22108             : 
   22109       25881 : THREADED_TEST(InstanceCheckOnInstanceAccessor) {
   22110           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22111           6 :   LocalContext context;
   22112          12 :   v8::HandleScope scope(context->GetIsolate());
   22113             : 
   22114           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22115           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22116             :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22117             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22118          18 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22119          36 :   CHECK(context->Global()
   22120             :             ->Set(context.local(), v8_str("f"),
   22121             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22122             :             .FromJust());
   22123             : 
   22124             :   printf("Testing positive ...\n");
   22125             :   CompileRun("var obj = new f();");
   22126          30 :   CHECK(templ->HasInstance(
   22127             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22128           6 :   CheckInstanceCheckedAccessors(true);
   22129             : 
   22130             :   printf("Testing negative ...\n");
   22131             :   CompileRun("var obj = {};"
   22132             :              "obj.__proto__ = new f();");
   22133          30 :   CHECK(!templ->HasInstance(
   22134             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22135          12 :   CheckInstanceCheckedAccessors(false);
   22136           6 : }
   22137             : 
   22138          90 : static void EmptyInterceptorGetter(
   22139          90 :     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22140             : 
   22141          30 : static void EmptyInterceptorSetter(
   22142             :     Local<Name> name, Local<Value> value,
   22143          30 :     const v8::PropertyCallbackInfo<v8::Value>& info) {}
   22144             : 
   22145       25881 : THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
   22146           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22147           6 :   LocalContext context;
   22148          12 :   v8::HandleScope scope(context->GetIsolate());
   22149             : 
   22150           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22151           6 :   Local<ObjectTemplate> inst = templ->InstanceTemplate();
   22152             :   templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
   22153          12 :       EmptyInterceptorGetter, EmptyInterceptorSetter));
   22154             :   inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
   22155             :                     Local<Value>(), v8::DEFAULT, v8::None,
   22156          18 :                     v8::AccessorSignature::New(context->GetIsolate(), templ));
   22157          36 :   CHECK(context->Global()
   22158             :             ->Set(context.local(), v8_str("f"),
   22159             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22160             :             .FromJust());
   22161             : 
   22162             :   printf("Testing positive ...\n");
   22163             :   CompileRun("var obj = new f();");
   22164          30 :   CHECK(templ->HasInstance(
   22165             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22166           6 :   CheckInstanceCheckedAccessors(true);
   22167             : 
   22168             :   printf("Testing negative ...\n");
   22169             :   CompileRun("var obj = {};"
   22170             :              "obj.__proto__ = new f();");
   22171          30 :   CHECK(!templ->HasInstance(
   22172             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22173          12 :   CheckInstanceCheckedAccessors(false);
   22174           6 : }
   22175             : 
   22176             : 
   22177       25881 : THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
   22178           6 :   v8::internal::FLAG_allow_natives_syntax = true;
   22179           6 :   LocalContext context;
   22180          12 :   v8::HandleScope scope(context->GetIsolate());
   22181             : 
   22182           6 :   Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
   22183           6 :   Local<ObjectTemplate> proto = templ->PrototypeTemplate();
   22184             :   proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
   22185             :                      InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
   22186             :                      v8::None,
   22187          18 :                      v8::AccessorSignature::New(context->GetIsolate(), templ));
   22188          36 :   CHECK(context->Global()
   22189             :             ->Set(context.local(), v8_str("f"),
   22190             :                   templ->GetFunction(context.local()).ToLocalChecked())
   22191             :             .FromJust());
   22192             : 
   22193             :   printf("Testing positive ...\n");
   22194             :   CompileRun("var obj = new f();");
   22195          30 :   CHECK(templ->HasInstance(
   22196             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22197           6 :   CheckInstanceCheckedAccessors(true);
   22198             : 
   22199             :   printf("Testing negative ...\n");
   22200             :   CompileRun("var obj = {};"
   22201             :              "obj.__proto__ = new f();");
   22202          30 :   CHECK(!templ->HasInstance(
   22203             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22204           6 :   CheckInstanceCheckedAccessors(false);
   22205             : 
   22206             :   printf("Testing positive with modified prototype chain ...\n");
   22207             :   CompileRun("var obj = new f();"
   22208             :              "var pro = {};"
   22209             :              "pro.__proto__ = obj.__proto__;"
   22210             :              "obj.__proto__ = pro;");
   22211          30 :   CHECK(templ->HasInstance(
   22212             :       context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
   22213          12 :   CheckInstanceCheckedAccessors(true);
   22214           6 : }
   22215             : 
   22216             : 
   22217       25880 : TEST(TryFinallyMessage) {
   22218           5 :   LocalContext context;
   22219          10 :   v8::HandleScope scope(context->GetIsolate());
   22220             :   {
   22221             :     // Test that the original error message is not lost if there is a
   22222             :     // recursive call into Javascript is done in the finally block, e.g. to
   22223             :     // initialize an IC. (crbug.com/129171)
   22224           5 :     TryCatch try_catch(context->GetIsolate());
   22225             :     const char* trigger_ic =
   22226             :         "try {                      \n"
   22227             :         "  throw new Error('test'); \n"
   22228             :         "} finally {                \n"
   22229             :         "  var x = 0;               \n"
   22230             :         "  x++;                     \n"  // Trigger an IC initialization here.
   22231             :         "}                          \n";
   22232             :     CompileRun(trigger_ic);
   22233           5 :     CHECK(try_catch.HasCaught());
   22234           5 :     Local<Message> message = try_catch.Message();
   22235           5 :     CHECK(!message.IsEmpty());
   22236          10 :     CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
   22237             :   }
   22238             : 
   22239             :   {
   22240             :     // Test that the original exception message is indeed overwritten if
   22241             :     // a new error is thrown in the finally block.
   22242           5 :     TryCatch try_catch(context->GetIsolate());
   22243             :     const char* throw_again =
   22244             :         "try {                       \n"
   22245             :         "  throw new Error('test');  \n"
   22246             :         "} finally {                 \n"
   22247             :         "  var x = 0;                \n"
   22248             :         "  x++;                      \n"
   22249             :         "  throw new Error('again'); \n"  // This is the new uncaught error.
   22250             :         "}                           \n";
   22251             :     CompileRun(throw_again);
   22252           5 :     CHECK(try_catch.HasCaught());
   22253           5 :     Local<Message> message = try_catch.Message();
   22254           5 :     CHECK(!message.IsEmpty());
   22255          10 :     CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
   22256           5 :   }
   22257           5 : }
   22258             : 
   22259             : 
   22260          96 : static void Helper137002(bool do_store,
   22261             :                          bool polymorphic,
   22262             :                          bool remove_accessor,
   22263             :                          bool interceptor) {
   22264          96 :   LocalContext context;
   22265          96 :   Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
   22266          96 :   if (interceptor) {
   22267             :     templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
   22268          48 :                                                             FooSetInterceptor));
   22269             :   } else {
   22270             :     templ->SetAccessor(v8_str("foo"),
   22271             :                        GetterWhichReturns42,
   22272          48 :                        SetterWhichSetsYOnThisTo23);
   22273             :   }
   22274         576 :   CHECK(context->Global()
   22275             :             ->Set(context.local(), v8_str("obj"),
   22276             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22277             :             .FromJust());
   22278             : 
   22279             :   // Turn monomorphic on slow object with native accessor, then turn
   22280             :   // polymorphic, finally optimize to create negative lookup and fail.
   22281             :   CompileRun(do_store ?
   22282             :              "function f(x) { x.foo = void 0; }" :
   22283          96 :              "function f(x) { return x.foo; }");
   22284             :   CompileRun("obj.y = void 0;");
   22285          96 :   if (!interceptor) {
   22286             :     CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
   22287             :   }
   22288             :   CompileRun("obj.__proto__ = null;"
   22289             :              "f(obj); f(obj); f(obj);");
   22290          96 :   if (polymorphic) {
   22291             :     CompileRun("f({});");
   22292             :   }
   22293             :   CompileRun("obj.y = void 0;"
   22294             :              "%OptimizeFunctionOnNextCall(f);");
   22295          96 :   if (remove_accessor) {
   22296             :     CompileRun("delete obj.foo;");
   22297             :   }
   22298             :   CompileRun("var result = f(obj);");
   22299          96 :   if (do_store) {
   22300             :     CompileRun("result = obj.y;");
   22301             :   }
   22302          96 :   if (remove_accessor && !interceptor) {
   22303         120 :     CHECK(context->Global()
   22304             :               ->Get(context.local(), v8_str("result"))
   22305             :               .ToLocalChecked()
   22306             :               ->IsUndefined());
   22307             :   } else {
   22308         432 :     CHECK_EQ(do_store ? 23 : 42, context->Global()
   22309             :                                      ->Get(context.local(), v8_str("result"))
   22310             :                                      .ToLocalChecked()
   22311             :                                      ->Int32Value(context.local())
   22312             :                                      .FromJust());
   22313          96 :   }
   22314          96 : }
   22315             : 
   22316             : 
   22317       25881 : THREADED_TEST(Regress137002a) {
   22318           6 :   i::FLAG_allow_natives_syntax = true;
   22319           6 :   i::FLAG_compilation_cache = false;
   22320           6 :   v8::HandleScope scope(CcTest::isolate());
   22321         102 :   for (int i = 0; i < 16; i++) {
   22322          96 :     Helper137002(i & 8, i & 4, i & 2, i & 1);
   22323           6 :   }
   22324           6 : }
   22325             : 
   22326             : 
   22327       25881 : THREADED_TEST(Regress137002b) {
   22328           6 :   i::FLAG_allow_natives_syntax = true;
   22329           6 :   LocalContext context;
   22330           6 :   v8::Isolate* isolate = context->GetIsolate();
   22331          12 :   v8::HandleScope scope(isolate);
   22332           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22333             :   templ->SetAccessor(v8_str("foo"),
   22334             :                      GetterWhichReturns42,
   22335           6 :                      SetterWhichSetsYOnThisTo23);
   22336          36 :   CHECK(context->Global()
   22337             :             ->Set(context.local(), v8_str("obj"),
   22338             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22339             :             .FromJust());
   22340             : 
   22341             :   // Turn monomorphic on slow object with native accessor, then just
   22342             :   // delete the property and fail.
   22343             :   CompileRun("function load(x) { return x.foo; }"
   22344             :              "function store(x) { x.foo = void 0; }"
   22345             :              "function keyed_load(x, key) { return x[key]; }"
   22346             :              // Second version of function has a different source (add void 0)
   22347             :              // so that it does not share code with the first version.  This
   22348             :              // ensures that the ICs are monomorphic.
   22349             :              "function load2(x) { void 0; return x.foo; }"
   22350             :              "function store2(x) { void 0; x.foo = void 0; }"
   22351             :              "function keyed_load2(x, key) { void 0; return x[key]; }"
   22352             : 
   22353             :              "obj.y = void 0;"
   22354             :              "obj.__proto__ = null;"
   22355             :              "var subobj = {};"
   22356             :              "subobj.y = void 0;"
   22357             :              "subobj.__proto__ = obj;"
   22358             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22359             : 
   22360             :              // Make the ICs monomorphic.
   22361             :              "load(obj); load(obj);"
   22362             :              "load2(subobj); load2(subobj);"
   22363             :              "store(obj); store(obj);"
   22364             :              "store2(subobj); store2(subobj);"
   22365             :              "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
   22366             :              "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
   22367             : 
   22368             :              // Actually test the shiny new ICs and better not crash. This
   22369             :              // serves as a regression test for issue 142088 as well.
   22370             :              "load(obj);"
   22371             :              "load2(subobj);"
   22372             :              "store(obj);"
   22373             :              "store2(subobj);"
   22374             :              "keyed_load(obj, 'foo');"
   22375             :              "keyed_load2(subobj, 'foo');"
   22376             : 
   22377             :              // Delete the accessor.  It better not be called any more now.
   22378             :              "delete obj.foo;"
   22379             :              "obj.y = void 0;"
   22380             :              "subobj.y = void 0;"
   22381             : 
   22382             :              "var load_result = load(obj);"
   22383             :              "var load_result2 = load2(subobj);"
   22384             :              "var keyed_load_result = keyed_load(obj, 'foo');"
   22385             :              "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
   22386             :              "store(obj);"
   22387             :              "store2(subobj);"
   22388             :              "var y_from_obj = obj.y;"
   22389             :              "var y_from_subobj = subobj.y;");
   22390          30 :   CHECK(context->Global()
   22391             :             ->Get(context.local(), v8_str("load_result"))
   22392             :             .ToLocalChecked()
   22393             :             ->IsUndefined());
   22394          30 :   CHECK(context->Global()
   22395             :             ->Get(context.local(), v8_str("load_result2"))
   22396             :             .ToLocalChecked()
   22397             :             ->IsUndefined());
   22398          30 :   CHECK(context->Global()
   22399             :             ->Get(context.local(), v8_str("keyed_load_result"))
   22400             :             .ToLocalChecked()
   22401             :             ->IsUndefined());
   22402          30 :   CHECK(context->Global()
   22403             :             ->Get(context.local(), v8_str("keyed_load_result2"))
   22404             :             .ToLocalChecked()
   22405             :             ->IsUndefined());
   22406          30 :   CHECK(context->Global()
   22407             :             ->Get(context.local(), v8_str("y_from_obj"))
   22408             :             .ToLocalChecked()
   22409             :             ->IsUndefined());
   22410          30 :   CHECK(context->Global()
   22411             :             ->Get(context.local(), v8_str("y_from_subobj"))
   22412             :             .ToLocalChecked()
   22413           6 :             ->IsUndefined());
   22414           6 : }
   22415             : 
   22416             : 
   22417       25881 : THREADED_TEST(Regress142088) {
   22418           6 :   i::FLAG_allow_natives_syntax = true;
   22419           6 :   LocalContext context;
   22420           6 :   v8::Isolate* isolate = context->GetIsolate();
   22421          12 :   v8::HandleScope scope(isolate);
   22422           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22423             :   templ->SetAccessor(v8_str("foo"),
   22424             :                      GetterWhichReturns42,
   22425           6 :                      SetterWhichSetsYOnThisTo23);
   22426          36 :   CHECK(context->Global()
   22427             :             ->Set(context.local(), v8_str("obj"),
   22428             :                   templ->NewInstance(context.local()).ToLocalChecked())
   22429             :             .FromJust());
   22430             : 
   22431             :   CompileRun("function load(x) { return x.foo; }"
   22432             :              "var o = Object.create(obj);"
   22433             :              "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
   22434           6 :              "load(o); load(o); load(o); load(o);");
   22435           6 : }
   22436             : 
   22437             : 
   22438       25881 : THREADED_TEST(Regress137496) {
   22439           6 :   i::FLAG_expose_gc = true;
   22440           6 :   LocalContext context;
   22441          12 :   v8::HandleScope scope(context->GetIsolate());
   22442             : 
   22443             :   // Compile a try-finally clause where the finally block causes a GC
   22444             :   // while there still is a message pending for external reporting.
   22445          12 :   TryCatch try_catch(context->GetIsolate());
   22446           6 :   try_catch.SetVerbose(true);
   22447             :   CompileRun("try { throw new Error(); } finally { gc(); }");
   22448          12 :   CHECK(try_catch.HasCaught());
   22449           6 : }
   22450             : 
   22451             : 
   22452       25881 : THREADED_TEST(Regress157124) {
   22453           6 :   LocalContext context;
   22454           6 :   v8::Isolate* isolate = context->GetIsolate();
   22455          12 :   v8::HandleScope scope(isolate);
   22456           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   22457          12 :   Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
   22458           6 :   obj->GetIdentityHash();
   22459             :   obj->DeletePrivate(context.local(),
   22460           6 :                      v8::Private::ForApi(isolate, v8_str("Bug")))
   22461          18 :       .FromJust();
   22462           6 : }
   22463             : 
   22464             : 
   22465       25881 : THREADED_TEST(Regress2535) {
   22466           6 :   LocalContext context;
   22467          12 :   v8::HandleScope scope(context->GetIsolate());
   22468             :   Local<Value> set_value = CompileRun("new Set();");
   22469             :   Local<Object> set_object(Local<Object>::Cast(set_value));
   22470           6 :   CHECK_EQ(0, set_object->InternalFieldCount());
   22471             :   Local<Value> map_value = CompileRun("new Map();");
   22472             :   Local<Object> map_object(Local<Object>::Cast(map_value));
   22473          12 :   CHECK_EQ(0, map_object->InternalFieldCount());
   22474           6 : }
   22475             : 
   22476             : 
   22477       25881 : THREADED_TEST(Regress2746) {
   22478           6 :   LocalContext context;
   22479           6 :   v8::Isolate* isolate = context->GetIsolate();
   22480          12 :   v8::HandleScope scope(isolate);
   22481           6 :   Local<Object> obj = Object::New(isolate);
   22482           6 :   Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
   22483          12 :   CHECK(
   22484             :       obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
   22485           6 :   Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
   22486           6 :   CHECK(!value.IsEmpty());
   22487          12 :   CHECK(value->IsUndefined());
   22488           6 : }
   22489             : 
   22490             : 
   22491       25881 : THREADED_TEST(Regress260106) {
   22492           6 :   LocalContext context;
   22493           6 :   v8::Isolate* isolate = context->GetIsolate();
   22494          12 :   v8::HandleScope scope(isolate);
   22495             :   Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
   22496           6 :                                                         DummyCallHandler);
   22497             :   CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
   22498             :   Local<Function> function =
   22499          12 :       templ->GetFunction(context.local()).ToLocalChecked();
   22500           6 :   CHECK(!function.IsEmpty());
   22501          12 :   CHECK(function->IsFunction());
   22502           6 : }
   22503             : 
   22504       25881 : THREADED_TEST(JSONParseObject) {
   22505           6 :   LocalContext context;
   22506          12 :   HandleScope scope(context->GetIsolate());
   22507             :   Local<Value> obj =
   22508          12 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22509           6 :   Local<Object> global = context->Global();
   22510          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22511          12 :   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
   22512           6 : }
   22513             : 
   22514       25881 : THREADED_TEST(JSONParseNumber) {
   22515           6 :   LocalContext context;
   22516          12 :   HandleScope scope(context->GetIsolate());
   22517             :   Local<Value> obj =
   22518          12 :       v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
   22519           6 :   Local<Object> global = context->Global();
   22520          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22521          12 :   ExpectString("JSON.stringify(obj)", "42");
   22522           6 : }
   22523             : 
   22524             : namespace {
   22525          42 : void TestJSONParseArray(Local<Context> context, const char* input_str,
   22526             :                         const char* expected_output_str,
   22527             :                         i::ElementsKind expected_elements_kind) {
   22528             :   Local<Value> obj =
   22529          42 :       v8::JSON::Parse(context, v8_str(input_str)).ToLocalChecked();
   22530             : 
   22531             :   i::Handle<i::JSArray> a =
   22532          42 :       i::Handle<i::JSArray>::cast(v8::Utils::OpenHandle(*obj));
   22533          42 :   CHECK_EQ(expected_elements_kind, a->GetElementsKind());
   22534             : 
   22535          42 :   Local<Object> global = context->Global();
   22536         126 :   global->Set(context, v8_str("obj"), obj).FromJust();
   22537          42 :   ExpectString("JSON.stringify(obj)", expected_output_str);
   22538          42 : }
   22539             : }  // namespace
   22540             : 
   22541       25881 : THREADED_TEST(JSONParseArray) {
   22542           6 :   LocalContext context;
   22543          12 :   HandleScope scope(context->GetIsolate());
   22544             : 
   22545             :   TestJSONParseArray(context.local(), "[0, 1, 2]", "[0,1,2]",
   22546           6 :                      i::PACKED_SMI_ELEMENTS);
   22547             :   TestJSONParseArray(context.local(), "[0, 1.2, 2]", "[0,1.2,2]",
   22548           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   22549             :   TestJSONParseArray(context.local(), "[0.2, 1, 2]", "[0.2,1,2]",
   22550           6 :                      i::PACKED_DOUBLE_ELEMENTS);
   22551             :   TestJSONParseArray(context.local(), "[0, \"a\", 2]", "[0,\"a\",2]",
   22552           6 :                      i::PACKED_ELEMENTS);
   22553             :   TestJSONParseArray(context.local(), "[\"a\", 1, 2]", "[\"a\",1,2]",
   22554           6 :                      i::PACKED_ELEMENTS);
   22555             :   TestJSONParseArray(context.local(), "[\"a\", 1.2, 2]", "[\"a\",1.2,2]",
   22556           6 :                      i::PACKED_ELEMENTS);
   22557             :   TestJSONParseArray(context.local(), "[0, 1.2, \"a\"]", "[0,1.2,\"a\"]",
   22558          12 :                      i::PACKED_ELEMENTS);
   22559           6 : }
   22560             : 
   22561       25881 : THREADED_TEST(JSONStringifyObject) {
   22562           6 :   LocalContext context;
   22563          12 :   HandleScope scope(context->GetIsolate());
   22564             :   Local<Value> value =
   22565           6 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22566           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   22567           6 :   Local<Object> global = context->Global();
   22568          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22569             :   Local<String> json =
   22570          12 :       v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
   22571          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   22572          12 :   ExpectString("JSON.stringify(obj)", *utf8);
   22573           6 : }
   22574             : 
   22575       25881 : THREADED_TEST(JSONStringifyObjectWithGap) {
   22576           6 :   LocalContext context;
   22577          12 :   HandleScope scope(context->GetIsolate());
   22578             :   Local<Value> value =
   22579           6 :       v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   22580           6 :   Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
   22581           6 :   Local<Object> global = context->Global();
   22582          24 :   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   22583             :   Local<String> json =
   22584          18 :       v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
   22585          12 :   v8::String::Utf8Value utf8(context->GetIsolate(), json);
   22586          12 :   ExpectString("JSON.stringify(obj, null,  '*')", *utf8);
   22587           6 : }
   22588             : 
   22589             : #if V8_OS_POSIX
   22590             : class ThreadInterruptTest {
   22591             :  public:
   22592           6 :   ThreadInterruptTest() : sem_(0), sem_value_(0) { }
   22593           6 :   ~ThreadInterruptTest() = default;
   22594             : 
   22595           6 :   void RunTest() {
   22596             :     InterruptThread i_thread(this);
   22597           6 :     i_thread.Start();
   22598             : 
   22599           6 :     sem_.Wait();
   22600           6 :     CHECK_EQ(kExpectedValue, sem_value_);
   22601           6 :   }
   22602             : 
   22603             :  private:
   22604             :   static const int kExpectedValue = 1;
   22605             : 
   22606           6 :   class InterruptThread : public v8::base::Thread {
   22607             :    public:
   22608             :     explicit InterruptThread(ThreadInterruptTest* test)
   22609           6 :         : Thread(Options("InterruptThread")), test_(test) {}
   22610             : 
   22611           6 :     void Run() override {
   22612             :       struct sigaction action;
   22613             : 
   22614             :       // Ensure that we'll enter waiting condition
   22615           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   22616             : 
   22617             :       // Setup signal handler
   22618             :       memset(&action, 0, sizeof(action));
   22619           6 :       action.sa_handler = SignalHandler;
   22620           6 :       sigaction(SIGCHLD, &action, nullptr);
   22621             : 
   22622             :       // Send signal
   22623           6 :       kill(getpid(), SIGCHLD);
   22624             : 
   22625             :       // Ensure that if wait has returned because of error
   22626           6 :       v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   22627             : 
   22628             :       // Set value and signal semaphore
   22629           6 :       test_->sem_value_ = 1;
   22630           6 :       test_->sem_.Signal();
   22631           6 :     }
   22632             : 
   22633           6 :     static void SignalHandler(int signal) {
   22634           6 :     }
   22635             : 
   22636             :    private:
   22637             :      ThreadInterruptTest* test_;
   22638             :   };
   22639             : 
   22640             :   v8::base::Semaphore sem_;
   22641             :   volatile int sem_value_;
   22642             : };
   22643             : 
   22644             : 
   22645       25881 : THREADED_TEST(SemaphoreInterruption) {
   22646          12 :   ThreadInterruptTest().RunTest();
   22647           6 : }
   22648             : 
   22649             : 
   22650             : #endif  // V8_OS_POSIX
   22651             : 
   22652             : 
   22653           0 : void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22654           0 :   UNREACHABLE();
   22655             : }
   22656             : 
   22657             : 
   22658       25880 : TEST(JSONStringifyAccessCheck) {
   22659           5 :   v8::V8::Initialize();
   22660           5 :   v8::Isolate* isolate = CcTest::isolate();
   22661           5 :   v8::HandleScope scope(isolate);
   22662             : 
   22663             :   // Create an ObjectTemplate for global objects and install access
   22664             :   // check callbacks that will block access.
   22665             :   v8::Local<v8::ObjectTemplate> global_template =
   22666           5 :       v8::ObjectTemplate::New(isolate);
   22667           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   22668             : 
   22669             :   // Create a context and set an x property on it's global object.
   22670          10 :   LocalContext context0(nullptr, global_template);
   22671           5 :   v8::Local<v8::Object> global0 = context0->Global();
   22672          15 :   global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
   22673           5 :   ExpectString("JSON.stringify(this)", "{\"x\":42}");
   22674             : 
   22675          15 :   for (int i = 0; i < 2; i++) {
   22676          10 :     if (i == 1) {
   22677             :       // Install a toJSON function on the second run.
   22678             :       v8::Local<v8::FunctionTemplate> toJSON =
   22679           5 :           v8::FunctionTemplate::New(isolate, UnreachableCallback);
   22680             : 
   22681             :       global0->Set(context0.local(), v8_str("toJSON"),
   22682          25 :                    toJSON->GetFunction(context0.local()).ToLocalChecked())
   22683          10 :           .FromJust();
   22684             :     }
   22685             :     // Create a context with a different security token so that the
   22686             :     // failed access check callback will be called on each access.
   22687          10 :     LocalContext context1(nullptr, global_template);
   22688          50 :     CHECK(context1->Global()
   22689             :               ->Set(context1.local(), v8_str("other"), global0)
   22690             :               .FromJust());
   22691             : 
   22692          10 :     CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
   22693          10 :     CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
   22694          10 :     CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
   22695          15 :   }
   22696           5 : }
   22697             : 
   22698             : 
   22699             : bool access_check_fail_thrown = false;
   22700             : bool catch_callback_called = false;
   22701             : 
   22702             : 
   22703             : // Failed access check callback that performs a GC on each invocation.
   22704          80 : void FailedAccessCheckThrows(Local<v8::Object> target,
   22705             :                              v8::AccessType type,
   22706             :                              Local<v8::Value> data) {
   22707          80 :   access_check_fail_thrown = true;
   22708          80 :   i::PrintF("Access check failed. Error thrown.\n");
   22709             :   CcTest::isolate()->ThrowException(
   22710          80 :       v8::Exception::Error(v8_str("cross context")));
   22711          80 : }
   22712             : 
   22713             : 
   22714         300 : void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22715         300 :   for (int i = 0; i < args.Length(); i++) {
   22716          75 :     i::PrintF("%s\n", *String::Utf8Value(args.GetIsolate(), args[i]));
   22717             :   }
   22718          75 :   catch_callback_called = true;
   22719          75 : }
   22720             : 
   22721             : 
   22722           5 : void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   22723           5 :   v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
   22724          20 :   CHECK(
   22725             :       args[0]
   22726             :           ->ToObject(context)
   22727             :           .ToLocalChecked()
   22728             :           ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
   22729             :           .IsNothing());
   22730           5 : }
   22731             : 
   22732             : 
   22733          75 : void CheckCorrectThrow(const char* script) {
   22734             :   // Test that the script, when wrapped into a try-catch, triggers the catch
   22735             :   // clause due to failed access check throwing an exception.
   22736             :   // The subsequent try-catch should run without any exception.
   22737          75 :   access_check_fail_thrown = false;
   22738          75 :   catch_callback_called = false;
   22739             :   i::ScopedVector<char> source(1024);
   22740          75 :   i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
   22741             :   CompileRun(source.start());
   22742          75 :   CHECK(access_check_fail_thrown);
   22743          75 :   CHECK(catch_callback_called);
   22744             : 
   22745          75 :   access_check_fail_thrown = false;
   22746          75 :   catch_callback_called = false;
   22747             :   CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
   22748          75 :   CHECK(!access_check_fail_thrown);
   22749          75 :   CHECK(!catch_callback_called);
   22750          75 : }
   22751             : 
   22752             : 
   22753       25880 : TEST(AccessCheckThrows) {
   22754           5 :   i::FLAG_allow_natives_syntax = true;
   22755           5 :   v8::V8::Initialize();
   22756           5 :   v8::Isolate* isolate = CcTest::isolate();
   22757           5 :   isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
   22758           5 :   v8::HandleScope scope(isolate);
   22759             : 
   22760             :   // Create an ObjectTemplate for global objects and install access
   22761             :   // check callbacks that will block access.
   22762             :   v8::Local<v8::ObjectTemplate> global_template =
   22763           5 :       v8::ObjectTemplate::New(isolate);
   22764           5 :   global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
   22765             : 
   22766             :   // Create a context and set an x property on it's global object.
   22767          10 :   LocalContext context0(nullptr, global_template);
   22768           5 :   v8::Local<v8::Object> global0 = context0->Global();
   22769          15 :   CHECK(global0->Set(context0.local(), v8_str("x"), global0).FromJust());
   22770             : 
   22771             :   // Create a context with a different security token so that the
   22772             :   // failed access check callback will be called on each access.
   22773          10 :   LocalContext context1(nullptr, global_template);
   22774          25 :   CHECK(context1->Global()
   22775             :             ->Set(context1.local(), v8_str("other"), global0)
   22776             :             .FromJust());
   22777             : 
   22778             :   v8::Local<v8::FunctionTemplate> catcher_fun =
   22779           5 :       v8::FunctionTemplate::New(isolate, CatcherCallback);
   22780          35 :   CHECK(context1->Global()
   22781             :             ->Set(context1.local(), v8_str("catcher"),
   22782             :                   catcher_fun->GetFunction(context1.local()).ToLocalChecked())
   22783             :             .FromJust());
   22784             : 
   22785             :   v8::Local<v8::FunctionTemplate> has_own_property_fun =
   22786           5 :       v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
   22787          35 :   CHECK(context1->Global()
   22788             :             ->Set(context1.local(), v8_str("has_own_property"),
   22789             :                   has_own_property_fun->GetFunction(context1.local())
   22790             :                       .ToLocalChecked())
   22791             :             .FromJust());
   22792             : 
   22793             :   {
   22794           5 :     v8::TryCatch try_catch(isolate);
   22795           5 :     access_check_fail_thrown = false;
   22796             :     CompileRun("other.x;");
   22797           5 :     CHECK(access_check_fail_thrown);
   22798           5 :     CHECK(try_catch.HasCaught());
   22799             :   }
   22800             : 
   22801           5 :   CheckCorrectThrow("other.x");
   22802           5 :   CheckCorrectThrow("other[1]");
   22803           5 :   CheckCorrectThrow("JSON.stringify(other)");
   22804           5 :   CheckCorrectThrow("has_own_property(other, 'x')");
   22805           5 :   CheckCorrectThrow("%GetProperty(other, 'x')");
   22806           5 :   CheckCorrectThrow("%SetKeyedProperty(other, 'x', 'foo')");
   22807           5 :   CheckCorrectThrow("%SetNamedProperty(other, 'y', 'foo')");
   22808             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kSloppy) == 0);
   22809             :   STATIC_ASSERT(static_cast<int>(i::LanguageMode::kStrict) == 1);
   22810           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");  // 0 == SLOPPY
   22811           5 :   CheckCorrectThrow("%DeleteProperty(other, 'x', 1)");  // 1 == STRICT
   22812           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
   22813           5 :   CheckCorrectThrow("%DeleteProperty(other, '1', 1)");
   22814           5 :   CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
   22815           5 :   CheckCorrectThrow("%HasProperty(other, 'x')");
   22816           5 :   CheckCorrectThrow("Object.prototype.propertyIsEnumerable(other, 'x')");
   22817             :   // PROPERTY_ATTRIBUTES_NONE = 0
   22818             :   CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
   22819           5 :                         "other, 'x', null, null, 1)");
   22820             : 
   22821             :   // Reset the failed access check callback so it does not influence
   22822             :   // the other tests.
   22823          10 :   isolate->SetFailedAccessCheckCallbackFunction(nullptr);
   22824           5 : }
   22825             : 
   22826             : class RequestInterruptTestBase {
   22827             :  public:
   22828          35 :   RequestInterruptTestBase()
   22829             :       : env_(),
   22830          35 :         isolate_(env_->GetIsolate()),
   22831             :         sem_(0),
   22832             :         warmup_(20000),
   22833         105 :         should_continue_(true) {
   22834          35 :   }
   22835             : 
   22836          35 :   virtual ~RequestInterruptTestBase() = default;
   22837             : 
   22838             :   virtual void StartInterruptThread() = 0;
   22839             : 
   22840             :   virtual void TestBody() = 0;
   22841             : 
   22842          70 :   void RunTest() {
   22843          35 :     StartInterruptThread();
   22844             : 
   22845          35 :     v8::HandleScope handle_scope(isolate_);
   22846             : 
   22847          35 :     TestBody();
   22848             : 
   22849             :     // Verify we arrived here because interruptor was called
   22850             :     // not due to a bug causing us to exit the loop too early.
   22851          35 :     CHECK(!should_continue());
   22852          35 :   }
   22853             : 
   22854             :   void WakeUpInterruptor() {
   22855          35 :     sem_.Signal();
   22856             :   }
   22857             : 
   22858             :   bool should_continue() const { return should_continue_; }
   22859             : 
   22860      809396 :   bool ShouldContinue() {
   22861      809396 :     if (warmup_ > 0) {
   22862      600000 :       if (--warmup_ == 0) {
   22863             :         WakeUpInterruptor();
   22864             :       }
   22865             :     }
   22866             : 
   22867      809396 :     return should_continue_;
   22868             :   }
   22869             : 
   22870      708462 :   static void ShouldContinueCallback(
   22871     1416924 :       const v8::FunctionCallbackInfo<Value>& info) {
   22872             :     RequestInterruptTestBase* test =
   22873             :         reinterpret_cast<RequestInterruptTestBase*>(
   22874      708462 :             info.Data().As<v8::External>()->Value());
   22875      708462 :     info.GetReturnValue().Set(test->ShouldContinue());
   22876      708462 :   }
   22877             : 
   22878             :   LocalContext env_;
   22879             :   v8::Isolate* isolate_;
   22880             :   v8::base::Semaphore sem_;
   22881             :   int warmup_;
   22882             :   bool should_continue_;
   22883             : };
   22884             : 
   22885             : 
   22886          60 : class RequestInterruptTestBaseWithSimpleInterrupt
   22887             :     : public RequestInterruptTestBase {
   22888             :  public:
   22889          60 :   RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
   22890             : 
   22891          30 :   void StartInterruptThread() override { i_thread.Start(); }
   22892             : 
   22893             :  private:
   22894          30 :   class InterruptThread : public v8::base::Thread {
   22895             :    public:
   22896             :     explicit InterruptThread(RequestInterruptTestBase* test)
   22897          30 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   22898             : 
   22899          30 :     void Run() override {
   22900          30 :       test_->sem_.Wait();
   22901          30 :       test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   22902          30 :     }
   22903             : 
   22904          30 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   22905             :       reinterpret_cast<RequestInterruptTestBase*>(data)->
   22906          30 :           should_continue_ = false;
   22907          30 :     }
   22908             : 
   22909             :    private:
   22910             :      RequestInterruptTestBase* test_;
   22911             :   };
   22912             : 
   22913             :   InterruptThread i_thread;
   22914             : };
   22915             : 
   22916             : 
   22917          10 : class RequestInterruptTestWithFunctionCall
   22918             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22919             :  public:
   22920           5 :   void TestBody() override {
   22921             :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   22922          15 :                                          v8::External::New(isolate_, this))
   22923           5 :                                .ToLocalChecked();
   22924          25 :     CHECK(env_->Global()
   22925             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   22926             :               .FromJust());
   22927             : 
   22928             :     CompileRun("while (ShouldContinue()) { }");
   22929           5 :   }
   22930             : };
   22931             : 
   22932             : 
   22933          10 : class RequestInterruptTestWithMethodCall
   22934             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22935             :  public:
   22936           5 :   void TestBody() override {
   22937           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22938           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22939             :     proto->Set(v8_str("shouldContinue"),
   22940             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   22941          20 :                                      v8::External::New(isolate_, this)));
   22942          30 :     CHECK(env_->Global()
   22943             :               ->Set(env_.local(), v8_str("Klass"),
   22944             :                     t->GetFunction(env_.local()).ToLocalChecked())
   22945             :               .FromJust());
   22946             : 
   22947             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   22948           5 :   }
   22949             : };
   22950             : 
   22951             : 
   22952          10 : class RequestInterruptTestWithAccessor
   22953             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22954             :  public:
   22955           5 :   void TestBody() override {
   22956           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22957           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   22958             :     proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
   22959          15 :         isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
   22960          30 :     CHECK(env_->Global()
   22961             :               ->Set(env_.local(), v8_str("Klass"),
   22962             :                     t->GetFunction(env_.local()).ToLocalChecked())
   22963             :               .FromJust());
   22964             : 
   22965             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   22966           5 :   }
   22967             : };
   22968             : 
   22969             : 
   22970          10 : class RequestInterruptTestWithNativeAccessor
   22971             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   22972             :  public:
   22973           5 :   void TestBody() override {
   22974           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   22975          10 :     t->InstanceTemplate()->SetNativeDataProperty(
   22976             :         v8_str("shouldContinue"), &ShouldContinueNativeGetter, nullptr,
   22977          20 :         v8::External::New(isolate_, this));
   22978          30 :     CHECK(env_->Global()
   22979             :               ->Set(env_.local(), v8_str("Klass"),
   22980             :                     t->GetFunction(env_.local()).ToLocalChecked())
   22981             :               .FromJust());
   22982             : 
   22983             :     CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
   22984           5 :   }
   22985             : 
   22986             :  private:
   22987      100934 :   static void ShouldContinueNativeGetter(
   22988             :       Local<String> property,
   22989             :       const v8::PropertyCallbackInfo<v8::Value>& info) {
   22990             :     RequestInterruptTestBase* test =
   22991             :         reinterpret_cast<RequestInterruptTestBase*>(
   22992      100934 :             info.Data().As<v8::External>()->Value());
   22993      100934 :     info.GetReturnValue().Set(test->ShouldContinue());
   22994      100934 :   }
   22995             : };
   22996             : 
   22997             : 
   22998          10 : class RequestInterruptTestWithMethodCallAndInterceptor
   22999             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23000             :  public:
   23001           5 :   void TestBody() override {
   23002           5 :     v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
   23003           5 :     v8::Local<v8::Template> proto = t->PrototypeTemplate();
   23004             :     proto->Set(v8_str("shouldContinue"),
   23005             :                FunctionTemplate::New(isolate_, ShouldContinueCallback,
   23006          20 :                                      v8::External::New(isolate_, this)));
   23007           5 :     v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
   23008             :     instance_template->SetHandler(
   23009           5 :         v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
   23010             : 
   23011          30 :     CHECK(env_->Global()
   23012             :               ->Set(env_.local(), v8_str("Klass"),
   23013             :                     t->GetFunction(env_.local()).ToLocalChecked())
   23014             :               .FromJust());
   23015             : 
   23016             :     CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
   23017           5 :   }
   23018             : 
   23019             :  private:
   23020      100485 :   static void EmptyInterceptor(
   23021      100485 :       Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
   23022             : };
   23023             : 
   23024             : 
   23025          10 : class RequestInterruptTestWithMathAbs
   23026             :     : public RequestInterruptTestBaseWithSimpleInterrupt {
   23027             :  public:
   23028           5 :   void TestBody() override {
   23029             :     env_->Global()
   23030             :         ->Set(env_.local(), v8_str("WakeUpInterruptor"),
   23031             :               Function::New(env_.local(), WakeUpInterruptorCallback,
   23032          15 :                             v8::External::New(isolate_, this))
   23033          25 :                   .ToLocalChecked())
   23034          10 :         .FromJust();
   23035             : 
   23036             :     env_->Global()
   23037             :         ->Set(env_.local(), v8_str("ShouldContinue"),
   23038             :               Function::New(env_.local(), ShouldContinueCallback,
   23039          15 :                             v8::External::New(isolate_, this))
   23040          25 :                   .ToLocalChecked())
   23041          10 :         .FromJust();
   23042             : 
   23043           5 :     i::FLAG_allow_natives_syntax = true;
   23044             :     CompileRun("function loopish(o) {"
   23045             :                "  var pre = 10;"
   23046             :                "  while (o.abs(1) > 0) {"
   23047             :                "    if (o.abs(1) >= 0 && !ShouldContinue()) break;"
   23048             :                "    if (pre > 0) {"
   23049             :                "      if (--pre === 0) WakeUpInterruptor(o === Math);"
   23050             :                "    }"
   23051             :                "  }"
   23052             :                "}"
   23053             :                "var i = 50;"
   23054             :                "var obj = {abs: function () { return i-- }, x: null};"
   23055             :                "delete obj.x;"
   23056             :                "loopish(obj);"
   23057             :                "%OptimizeFunctionOnNextCall(loopish);"
   23058             :                "loopish(Math);");
   23059             : 
   23060           5 :     i::FLAG_allow_natives_syntax = false;
   23061           5 :   }
   23062             : 
   23063             :  private:
   23064          10 :   static void WakeUpInterruptorCallback(
   23065          15 :       const v8::FunctionCallbackInfo<Value>& info) {
   23066          10 :     if (!info[0]->BooleanValue(info.GetIsolate())) {
   23067          10 :       return;
   23068             :     }
   23069             : 
   23070             :     RequestInterruptTestBase* test =
   23071             :         reinterpret_cast<RequestInterruptTestBase*>(
   23072           5 :             info.Data().As<v8::External>()->Value());
   23073             :     test->WakeUpInterruptor();
   23074             :   }
   23075             : 
   23076      104923 :   static void ShouldContinueCallback(
   23077      209846 :       const v8::FunctionCallbackInfo<Value>& info) {
   23078      104923 :     RequestInterruptTestBase* test =
   23079             :         reinterpret_cast<RequestInterruptTestBase*>(
   23080      104923 :             info.Data().As<v8::External>()->Value());
   23081             :     info.GetReturnValue().Set(test->should_continue());
   23082      104923 :   }
   23083             : };
   23084             : 
   23085             : 
   23086       25880 : TEST(RequestInterruptTestWithFunctionCall) {
   23087          15 :   RequestInterruptTestWithFunctionCall().RunTest();
   23088           5 : }
   23089             : 
   23090             : 
   23091       25880 : TEST(RequestInterruptTestWithMethodCall) {
   23092          15 :   RequestInterruptTestWithMethodCall().RunTest();
   23093           5 : }
   23094             : 
   23095             : 
   23096       25880 : TEST(RequestInterruptTestWithAccessor) {
   23097          15 :   RequestInterruptTestWithAccessor().RunTest();
   23098           5 : }
   23099             : 
   23100             : 
   23101       25880 : TEST(RequestInterruptTestWithNativeAccessor) {
   23102          15 :   RequestInterruptTestWithNativeAccessor().RunTest();
   23103           5 : }
   23104             : 
   23105             : 
   23106       25880 : TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
   23107          15 :   RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
   23108           5 : }
   23109             : 
   23110             : 
   23111       25880 : TEST(RequestInterruptTestWithMathAbs) {
   23112          15 :   RequestInterruptTestWithMathAbs().RunTest();
   23113           5 : }
   23114             : 
   23115             : 
   23116          10 : class RequestMultipleInterrupts : public RequestInterruptTestBase {
   23117             :  public:
   23118          10 :   RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
   23119             : 
   23120           5 :   void StartInterruptThread() override { i_thread.Start(); }
   23121             : 
   23122           5 :   void TestBody() override {
   23123             :     Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
   23124          15 :                                          v8::External::New(isolate_, this))
   23125           5 :                                .ToLocalChecked();
   23126          25 :     CHECK(env_->Global()
   23127             :               ->Set(env_.local(), v8_str("ShouldContinue"), func)
   23128             :               .FromJust());
   23129             : 
   23130             :     CompileRun("while (ShouldContinue()) { }");
   23131           5 :   }
   23132             : 
   23133             :  private:
   23134           5 :   class InterruptThread : public v8::base::Thread {
   23135             :    public:
   23136             :     enum { NUM_INTERRUPTS = 10 };
   23137             :     explicit InterruptThread(RequestMultipleInterrupts* test)
   23138           5 :         : Thread(Options("RequestInterruptTest")), test_(test) {}
   23139             : 
   23140           5 :     void Run() override {
   23141           5 :       test_->sem_.Wait();
   23142          55 :       for (int i = 0; i < NUM_INTERRUPTS; i++) {
   23143          50 :         test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
   23144             :       }
   23145           5 :     }
   23146             : 
   23147          50 :     static void OnInterrupt(v8::Isolate* isolate, void* data) {
   23148             :       RequestMultipleInterrupts* test =
   23149             :           reinterpret_cast<RequestMultipleInterrupts*>(data);
   23150          50 :       test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
   23151          50 :     }
   23152             : 
   23153             :    private:
   23154             :     RequestMultipleInterrupts* test_;
   23155             :   };
   23156             : 
   23157             :   InterruptThread i_thread;
   23158             :   int counter_;
   23159             : };
   23160             : 
   23161             : 
   23162       25880 : TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
   23163             : 
   23164             : 
   23165             : static bool interrupt_was_called = false;
   23166             : 
   23167             : 
   23168           5 : void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
   23169           5 :   interrupt_was_called = true;
   23170           5 : }
   23171             : 
   23172             : 
   23173       25880 : TEST(RequestInterruptSmallScripts) {
   23174           5 :   LocalContext env;
   23175           5 :   v8::Isolate* isolate = CcTest::isolate();
   23176          10 :   v8::HandleScope scope(isolate);
   23177             : 
   23178           5 :   interrupt_was_called = false;
   23179           5 :   isolate->RequestInterrupt(&SmallScriptsInterruptCallback, nullptr);
   23180             :   CompileRun("(function(x){return x;})(1);");
   23181          10 :   CHECK(interrupt_was_called);
   23182           5 : }
   23183             : 
   23184             : 
   23185             : static Local<Value> function_new_expected_env;
   23186          24 : static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
   23187          36 :   CHECK(
   23188             :       function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
   23189             :                                         info.Data())
   23190             :           .FromJust());
   23191             :   info.GetReturnValue().Set(17);
   23192          12 : }
   23193             : 
   23194             : 
   23195       25881 : THREADED_TEST(FunctionNew) {
   23196           6 :   LocalContext env;
   23197           6 :   v8::Isolate* isolate = env->GetIsolate();
   23198          12 :   v8::HandleScope scope(isolate);
   23199           6 :   Local<Object> data = v8::Object::New(isolate);
   23200           6 :   function_new_expected_env = data;
   23201             :   Local<Function> func =
   23202          12 :       Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
   23203          30 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   23204           6 :   Local<Value> result = CompileRun("func();");
   23205          18 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
   23206             :   // Serial number should be invalid => should not be cached.
   23207             :   auto serial_number =
   23208             :       i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
   23209          18 :                        ->shared()
   23210          12 :                        ->get_api_func_data()
   23211          12 :                        ->serial_number())
   23212             :           ->value();
   23213           6 :   CHECK_EQ(i::FunctionTemplateInfo::kInvalidSerialNumber, serial_number);
   23214             : 
   23215             :   // Verify that each Function::New creates a new function instance
   23216           6 :   Local<Object> data2 = v8::Object::New(isolate);
   23217           6 :   function_new_expected_env = data2;
   23218             :   Local<Function> func2 =
   23219          12 :       Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
   23220           6 :   CHECK(!func2->IsNull());
   23221          12 :   CHECK(!func->Equals(env.local(), func2).FromJust());
   23222          30 :   CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   23223           6 :   Local<Value> result2 = CompileRun("func2();");
   23224          24 :   CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
   23225           6 : }
   23226             : 
   23227             : namespace {
   23228             : 
   23229             : void Verify(v8::Isolate* isolate, Local<v8::Object> obj) {
   23230             : #if VERIFY_HEAP
   23231             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   23232             :   i::Handle<i::JSReceiver> i_obj = v8::Utils::OpenHandle(*obj);
   23233             :   i_obj->ObjectVerify(i_isolate);
   23234             : #endif
   23235             : }
   23236             : 
   23237             : }  // namespace
   23238             : 
   23239       25881 : THREADED_TEST(ObjectNew) {
   23240           6 :   LocalContext env;
   23241           6 :   v8::Isolate* isolate = env->GetIsolate();
   23242          12 :   v8::HandleScope scope(isolate);
   23243             :   {
   23244             :     // Verify that Object::New(null) produces an object with a null
   23245             :     // [[Prototype]].
   23246             :     Local<v8::Object> obj =
   23247           6 :         v8::Object::New(isolate, v8::Null(isolate), nullptr, nullptr, 0);
   23248          12 :     CHECK(obj->GetPrototype()->IsNull());
   23249             :     Verify(isolate, obj);
   23250           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23251           6 :     CHECK_EQ(0, keys->Length());
   23252             :   }
   23253             :   {
   23254             :     // Verify that Object::New(proto) produces an object with
   23255             :     // proto as it's [[Prototype]].
   23256           6 :     Local<v8::Object> proto = v8::Object::New(isolate);
   23257             :     Local<v8::Object> obj =
   23258           6 :         v8::Object::New(isolate, proto, nullptr, nullptr, 0);
   23259             :     Verify(isolate, obj);
   23260          12 :     CHECK(obj->GetPrototype()->SameValue(proto));
   23261             :   }
   23262             :   {
   23263             :     // Verify that the properties are installed correctly.
   23264          18 :     Local<v8::Name> names[3] = {v8_str("a"), v8_str("b"), v8_str("c")};
   23265           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23266             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23267           6 :                                             values, arraysize(values));
   23268             :     Verify(isolate, obj);
   23269           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23270           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23271          18 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23272          54 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23273          54 :       CHECK(values[i]->SameValue(
   23274             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23275             :     }
   23276             :   }
   23277             :   {
   23278             :     // Same as above, but with non-null prototype.
   23279           6 :     Local<v8::Object> proto = v8::Object::New(isolate);
   23280          18 :     Local<v8::Name> names[3] = {v8_str("x"), v8_str("y"), v8_str("z")};
   23281           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23282             :     Local<v8::Object> obj =
   23283           6 :         v8::Object::New(isolate, proto, names, values, arraysize(values));
   23284          12 :     CHECK(obj->GetPrototype()->SameValue(proto));
   23285             :     Verify(isolate, obj);
   23286           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23287           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23288          18 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23289          54 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23290          54 :       CHECK(values[i]->SameValue(
   23291             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23292             :     }
   23293             :   }
   23294             :   {
   23295             :     // This has to work with duplicate names too.
   23296          18 :     Local<v8::Name> names[3] = {v8_str("a"), v8_str("a"), v8_str("a")};
   23297           6 :     Local<v8::Value> values[3] = {v8_num(1), v8_num(2), v8_num(3)};
   23298             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23299           6 :                                             values, arraysize(values));
   23300             :     Verify(isolate, obj);
   23301           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23302           6 :     CHECK_EQ(1, keys->Length());
   23303          18 :     CHECK(v8_str("a")->SameValue(keys->Get(env.local(), 0).ToLocalChecked()));
   23304          24 :     CHECK(v8_num(3)->SameValue(
   23305             :         obj->Get(env.local(), v8_str("a")).ToLocalChecked()));
   23306             :   }
   23307             :   {
   23308             :     // This has to work with array indices too.
   23309          12 :     Local<v8::Name> names[2] = {v8_str("0"), v8_str("1")};
   23310           6 :     Local<v8::Value> values[2] = {v8_num(0), v8_num(1)};
   23311             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23312           6 :                                             values, arraysize(values));
   23313             :     Verify(isolate, obj);
   23314           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23315           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23316          12 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23317          36 :       CHECK(v8::Number::New(isolate, i)
   23318             :                 ->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23319          36 :       CHECK(values[i]->SameValue(obj->Get(env.local(), i).ToLocalChecked()));
   23320             :     }
   23321             :   }
   23322             :   {
   23323             :     // This has to work with mixed array indices / property names too.
   23324          12 :     Local<v8::Name> names[2] = {v8_str("0"), v8_str("x")};
   23325           6 :     Local<v8::Value> values[2] = {v8_num(42), v8_num(24)};
   23326             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23327           6 :                                             values, arraysize(values));
   23328             :     Verify(isolate, obj);
   23329           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23330           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23331             :     // 0 -> 42
   23332          18 :     CHECK(v8_num(0)->SameValue(keys->Get(env.local(), 0).ToLocalChecked()));
   23333          12 :     CHECK(
   23334             :         values[0]->SameValue(obj->Get(env.local(), names[0]).ToLocalChecked()));
   23335             :     // "x" -> 24
   23336          18 :     CHECK(v8_str("x")->SameValue(keys->Get(env.local(), 1).ToLocalChecked()));
   23337          12 :     CHECK(
   23338             :         values[1]->SameValue(obj->Get(env.local(), names[1]).ToLocalChecked()));
   23339             :   }
   23340             :   {
   23341             :     // Verify that this also works for a couple thousand properties.
   23342             :     size_t const kLength = 10 * 1024;
   23343       61446 :     Local<v8::Name> names[kLength];
   23344       61440 :     Local<v8::Value> values[kLength];
   23345       61440 :     for (size_t i = 0; i < arraysize(names); ++i) {
   23346       61440 :       std::ostringstream ost;
   23347       61440 :       ost << "a" << i;
   23348      122880 :       names[i] = v8_str(ost.str().c_str());
   23349       61440 :       values[i] = v8_num(static_cast<double>(i));
   23350       61440 :     }
   23351             :     Local<v8::Object> obj = v8::Object::New(isolate, v8::Null(isolate), names,
   23352           6 :                                             values, arraysize(names));
   23353             :     Verify(isolate, obj);
   23354           6 :     Local<Array> keys = obj->GetOwnPropertyNames(env.local()).ToLocalChecked();
   23355           6 :     CHECK_EQ(arraysize(names), keys->Length());
   23356       61440 :     for (uint32_t i = 0; i < arraysize(names); ++i) {
   23357      184320 :       CHECK(names[i]->SameValue(keys->Get(env.local(), i).ToLocalChecked()));
   23358      184320 :       CHECK(values[i]->SameValue(
   23359             :           obj->Get(env.local(), names[i]).ToLocalChecked()));
   23360             :     }
   23361           6 :   }
   23362           6 : }
   23363             : 
   23364       25880 : TEST(EscapableHandleScope) {
   23365           5 :   HandleScope outer_scope(CcTest::isolate());
   23366          10 :   LocalContext context;
   23367             :   const int runs = 10;
   23368          55 :   Local<String> values[runs];
   23369          50 :   for (int i = 0; i < runs; i++) {
   23370          50 :     v8::EscapableHandleScope inner_scope(CcTest::isolate());
   23371             :     Local<String> value;
   23372          50 :     if (i != 0) value = v8_str("escape value");
   23373          50 :     if (i < runs / 2) {
   23374          25 :       values[i] = inner_scope.Escape(value);
   23375             :     } else {
   23376             :       values[i] = inner_scope.EscapeMaybe(v8::MaybeLocal<String>(value))
   23377          25 :                       .ToLocalChecked();
   23378             :     }
   23379             :   }
   23380          50 :   for (int i = 0; i < runs; i++) {
   23381             :     Local<String> expected;
   23382          50 :     if (i != 0) {
   23383         135 :       CHECK(v8_str("escape value")
   23384             :                 ->Equals(context.local(), values[i])
   23385             :                 .FromJust());
   23386             :     } else {
   23387          10 :       CHECK(values[i].IsEmpty());
   23388             :     }
   23389           5 :   }
   23390           5 : }
   23391             : 
   23392             : 
   23393          20 : static void SetterWhichExpectsThisAndHolderToDiffer(
   23394             :     Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
   23395          20 :   CHECK(info.Holder() != info.This());
   23396          20 : }
   23397             : 
   23398             : 
   23399       25880 : TEST(Regress239669) {
   23400           5 :   LocalContext context;
   23401           5 :   v8::Isolate* isolate = context->GetIsolate();
   23402          10 :   v8::HandleScope scope(isolate);
   23403           5 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   23404             :   templ->SetAccessor(v8_str("x"), nullptr,
   23405           5 :                      SetterWhichExpectsThisAndHolderToDiffer);
   23406          30 :   CHECK(context->Global()
   23407             :             ->Set(context.local(), v8_str("P"),
   23408             :                   templ->NewInstance(context.local()).ToLocalChecked())
   23409             :             .FromJust());
   23410             :   CompileRun(
   23411             :       "function C1() {"
   23412             :       "  this.x = 23;"
   23413             :       "};"
   23414             :       "C1.prototype = P;"
   23415             :       "for (var i = 0; i < 4; i++ ) {"
   23416             :       "  new C1();"
   23417           5 :       "}");
   23418           5 : }
   23419             : 
   23420             : 
   23421             : class ApiCallOptimizationChecker {
   23422             :  private:
   23423             :   static Local<Object> data;
   23424             :   static Local<Object> receiver;
   23425             :   static Local<Object> holder;
   23426             :   static Local<Object> callee;
   23427             :   static int count;
   23428             : 
   23429         270 :   static void OptimizationCallback(
   23430        1350 :       const v8::FunctionCallbackInfo<v8::Value>& info) {
   23431         270 :     CHECK(data == info.Data());
   23432         270 :     CHECK(receiver == info.This());
   23433         270 :     if (info.Length() == 1) {
   23434         270 :       CHECK(v8_num(1)
   23435             :                 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
   23436             :                 .FromJust());
   23437             :     }
   23438         270 :     CHECK(holder == info.Holder());
   23439         270 :     count++;
   23440         270 :     info.GetReturnValue().Set(v8_str("returned"));
   23441         270 :   }
   23442             : 
   23443             :  public:
   23444             :   enum SignatureType {
   23445             :     kNoSignature,
   23446             :     kSignatureOnReceiver,
   23447             :     kSignatureOnPrototype
   23448             :   };
   23449             : 
   23450           5 :   void RunAll() {
   23451             :     SignatureType signature_types[] =
   23452           5 :       {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
   23453          20 :     for (unsigned i = 0; i < arraysize(signature_types); i++) {
   23454          15 :       SignatureType signature_type = signature_types[i];
   23455          45 :       for (int j = 0; j < 2; j++) {
   23456          30 :         bool global = j == 0;
   23457             :         int key = signature_type +
   23458          30 :             arraysize(signature_types) * (global ? 1 : 0);
   23459          30 :         Run(signature_type, global, key);
   23460             :       }
   23461             :     }
   23462           5 :   }
   23463             : 
   23464          30 :   void Run(SignatureType signature_type, bool global, int key) {
   23465          30 :     v8::Isolate* isolate = CcTest::isolate();
   23466          30 :     v8::HandleScope scope(isolate);
   23467             :     // Build a template for signature checks.
   23468             :     Local<v8::ObjectTemplate> signature_template;
   23469             :     Local<v8::Signature> signature;
   23470             :     {
   23471             :       Local<v8::FunctionTemplate> parent_template =
   23472          30 :         FunctionTemplate::New(isolate);
   23473             :       Local<v8::FunctionTemplate> function_template
   23474          30 :           = FunctionTemplate::New(isolate);
   23475          30 :       function_template->Inherit(parent_template);
   23476          30 :       switch (signature_type) {
   23477             :         case kNoSignature:
   23478             :           break;
   23479             :         case kSignatureOnReceiver:
   23480          10 :           signature = v8::Signature::New(isolate, function_template);
   23481          10 :           break;
   23482             :         case kSignatureOnPrototype:
   23483          10 :           signature = v8::Signature::New(isolate, parent_template);
   23484          10 :           break;
   23485             :       }
   23486          30 :       signature_template = function_template->InstanceTemplate();
   23487             :     }
   23488             :     // Global object must pass checks.
   23489             :     Local<v8::Context> context =
   23490          30 :         v8::Context::New(isolate, nullptr, signature_template);
   23491             :     v8::Context::Scope context_scope(context);
   23492             :     // Install regular object that can pass signature checks.
   23493             :     Local<Object> function_receiver =
   23494          30 :         signature_template->NewInstance(context).ToLocalChecked();
   23495         120 :     CHECK(context->Global()
   23496             :               ->Set(context, v8_str("function_receiver"), function_receiver)
   23497             :               .FromJust());
   23498             :     // Get the holder objects.
   23499             :     Local<Object> inner_global =
   23500          60 :         Local<Object>::Cast(context->Global()->GetPrototype());
   23501          30 :     data = Object::New(isolate);
   23502             :     Local<FunctionTemplate> function_template = FunctionTemplate::New(
   23503          30 :         isolate, OptimizationCallback, data, signature);
   23504             :     Local<Function> function =
   23505          30 :         function_template->GetFunction(context).ToLocalChecked();
   23506             :     Local<Object> global_holder = inner_global;
   23507             :     Local<Object> function_holder = function_receiver;
   23508          30 :     if (signature_type == kSignatureOnPrototype) {
   23509          10 :       function_holder = Local<Object>::Cast(function_holder->GetPrototype());
   23510          10 :       global_holder = Local<Object>::Cast(global_holder->GetPrototype());
   23511             :     }
   23512          90 :     global_holder->Set(context, v8_str("g_f"), function).FromJust();
   23513          60 :     global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
   23514          90 :     function_holder->Set(context, v8_str("f"), function).FromJust();
   23515          60 :     function_holder->SetAccessorProperty(v8_str("acc"), function, function);
   23516             :     // Initialize expected values.
   23517          30 :     callee = function;
   23518          30 :     count = 0;
   23519          30 :     if (global) {
   23520          15 :       receiver = context->Global();
   23521          15 :       holder = inner_global;
   23522             :     } else {
   23523          15 :       holder = function_receiver;
   23524             :       // If not using a signature, add something else to the prototype chain
   23525             :       // to test the case that holder != receiver
   23526          15 :       if (signature_type == kNoSignature) {
   23527             :         receiver = Local<Object>::Cast(CompileRun(
   23528             :             "var receiver_subclass = {};\n"
   23529             :             "receiver_subclass.__proto__ = function_receiver;\n"
   23530           5 :             "receiver_subclass"));
   23531             :       } else {
   23532             :         receiver = Local<Object>::Cast(CompileRun(
   23533             :           "var receiver_subclass = function_receiver;\n"
   23534          10 :           "receiver_subclass"));
   23535             :       }
   23536             :     }
   23537             :     // With no signature, the holder is not set.
   23538          30 :     if (signature_type == kNoSignature) holder = receiver;
   23539             :     // build wrap_function
   23540             :     i::ScopedVector<char> wrap_function(200);
   23541          30 :     if (global) {
   23542             :       i::SNPrintF(
   23543             :           wrap_function,
   23544             :           "function wrap_f_%d() { var f = g_f; return f(); }\n"
   23545             :           "function wrap_get_%d() { return this.g_acc; }\n"
   23546             :           "function wrap_set_%d() { return this.g_acc = 1; }\n",
   23547          15 :           key, key, key);
   23548             :     } else {
   23549             :       i::SNPrintF(
   23550             :           wrap_function,
   23551             :           "function wrap_f_%d() { return receiver_subclass.f(); }\n"
   23552             :           "function wrap_get_%d() { return receiver_subclass.acc; }\n"
   23553             :           "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
   23554          15 :           key, key, key);
   23555             :     }
   23556             :     // build source string
   23557             :     i::ScopedVector<char> source(1000);
   23558             :     i::SNPrintF(
   23559             :         source,
   23560             :         "%s\n"  // wrap functions
   23561             :         "function wrap_f() { return wrap_f_%d(); }\n"
   23562             :         "function wrap_get() { return wrap_get_%d(); }\n"
   23563             :         "function wrap_set() { return wrap_set_%d(); }\n"
   23564             :         "check = function(returned) {\n"
   23565             :         "  if (returned !== 'returned') { throw returned; }\n"
   23566             :         "}\n"
   23567             :         "\n"
   23568             :         "check(wrap_f());\n"
   23569             :         "check(wrap_f());\n"
   23570             :         "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
   23571             :         "check(wrap_f());\n"
   23572             :         "\n"
   23573             :         "check(wrap_get());\n"
   23574             :         "check(wrap_get());\n"
   23575             :         "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
   23576             :         "check(wrap_get());\n"
   23577             :         "\n"
   23578             :         "check = function(returned) {\n"
   23579             :         "  if (returned !== 1) { throw returned; }\n"
   23580             :         "}\n"
   23581             :         "check(wrap_set());\n"
   23582             :         "check(wrap_set());\n"
   23583             :         "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
   23584             :         "check(wrap_set());\n",
   23585          30 :         wrap_function.start(), key, key, key, key, key, key);
   23586          60 :     v8::TryCatch try_catch(isolate);
   23587             :     CompileRun(source.start());
   23588          30 :     CHECK(!try_catch.HasCaught());
   23589          60 :     CHECK_EQ(9, count);
   23590          30 :   }
   23591             : };
   23592             : 
   23593             : 
   23594             : Local<Object> ApiCallOptimizationChecker::data;
   23595             : Local<Object> ApiCallOptimizationChecker::receiver;
   23596             : Local<Object> ApiCallOptimizationChecker::holder;
   23597             : Local<Object> ApiCallOptimizationChecker::callee;
   23598             : int ApiCallOptimizationChecker::count = 0;
   23599             : 
   23600             : 
   23601       25880 : TEST(FunctionCallOptimization) {
   23602           5 :   i::FLAG_allow_natives_syntax = true;
   23603             :   ApiCallOptimizationChecker checker;
   23604           5 :   checker.RunAll();
   23605           5 : }
   23606             : 
   23607             : 
   23608       25880 : TEST(FunctionCallOptimizationMultipleArgs) {
   23609           5 :   i::FLAG_allow_natives_syntax = true;
   23610           5 :   LocalContext context;
   23611           5 :   v8::Isolate* isolate = context->GetIsolate();
   23612          10 :   v8::HandleScope scope(isolate);
   23613           5 :   Local<Object> global = context->Global();
   23614             :   Local<v8::Function> function =
   23615          10 :       Function::New(context.local(), Returns42).ToLocalChecked();
   23616          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   23617             :   CompileRun(
   23618             :       "function x_wrap() {\n"
   23619             :       "  for (var i = 0; i < 5; i++) {\n"
   23620             :       "    x(1,2,3);\n"
   23621             :       "  }\n"
   23622             :       "}\n"
   23623             :       "x_wrap();\n"
   23624             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   23625           5 :       "x_wrap();\n");
   23626           5 : }
   23627             : 
   23628             : 
   23629          50 : static void ReturnsSymbolCallback(
   23630         100 :     const v8::FunctionCallbackInfo<v8::Value>& info) {
   23631         100 :   info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
   23632          50 : }
   23633             : 
   23634             : 
   23635       25880 : TEST(ApiCallbackCanReturnSymbols) {
   23636           5 :   i::FLAG_allow_natives_syntax = true;
   23637           5 :   LocalContext context;
   23638           5 :   v8::Isolate* isolate = context->GetIsolate();
   23639          10 :   v8::HandleScope scope(isolate);
   23640           5 :   Local<Object> global = context->Global();
   23641             :   Local<v8::Function> function =
   23642          10 :       Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
   23643          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   23644             :   CompileRun(
   23645             :       "function x_wrap() {\n"
   23646             :       "  for (var i = 0; i < 5; i++) {\n"
   23647             :       "    x();\n"
   23648             :       "  }\n"
   23649             :       "}\n"
   23650             :       "x_wrap();\n"
   23651             :       "%OptimizeFunctionOnNextCall(x_wrap);"
   23652           5 :       "x_wrap();\n");
   23653           5 : }
   23654             : 
   23655             : 
   23656       25880 : TEST(EmptyApiCallback) {
   23657           5 :   LocalContext context;
   23658           5 :   auto isolate = context->GetIsolate();
   23659          10 :   v8::HandleScope scope(isolate);
   23660           5 :   auto global = context->Global();
   23661           5 :   auto function = FunctionTemplate::New(isolate)
   23662          15 :                       ->GetFunction(context.local())
   23663           5 :                       .ToLocalChecked();
   23664          20 :   global->Set(context.local(), v8_str("x"), function).FromJust();
   23665             : 
   23666             :   auto result = CompileRun("x()");
   23667          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23668             : 
   23669             :   result = CompileRun("x(1,2,3)");
   23670          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23671             : 
   23672             :   result = CompileRun("x.call(undefined)");
   23673          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23674             : 
   23675             :   result = CompileRun("x.call(null)");
   23676          10 :   CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
   23677             : 
   23678             :   result = CompileRun("7 + x.call(3) + 11");
   23679           5 :   CHECK(result->IsInt32());
   23680          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   23681             : 
   23682             :   result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
   23683           5 :   CHECK(result->IsInt32());
   23684          10 :   CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
   23685             : 
   23686             :   result = CompileRun("var y = []; x.call(y)");
   23687           5 :   CHECK(result->IsArray());
   23688             : 
   23689             :   result = CompileRun("x.call(y, 1, 2, 3, 4)");
   23690          10 :   CHECK(result->IsArray());
   23691           5 : }
   23692             : 
   23693             : 
   23694       25880 : TEST(SimpleSignatureCheck) {
   23695           5 :   LocalContext context;
   23696           5 :   auto isolate = context->GetIsolate();
   23697          10 :   v8::HandleScope scope(isolate);
   23698           5 :   auto global = context->Global();
   23699           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   23700           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   23701           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23702             :   global->Set(context.local(), v8_str("sig_obj"),
   23703          25 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23704          10 :       .FromJust();
   23705             :   global->Set(context.local(), v8_str("x"),
   23706          25 :               x->GetFunction(context.local()).ToLocalChecked())
   23707          10 :       .FromJust();
   23708             :   CompileRun("var s = new sig_obj();");
   23709             :   {
   23710           5 :     TryCatch try_catch(isolate);
   23711             :     CompileRun("x()");
   23712           5 :     CHECK(try_catch.HasCaught());
   23713             :   }
   23714             :   {
   23715           5 :     TryCatch try_catch(isolate);
   23716             :     CompileRun("x.call(1)");
   23717           5 :     CHECK(try_catch.HasCaught());
   23718             :   }
   23719             :   {
   23720           5 :     TryCatch try_catch(isolate);
   23721             :     auto result = CompileRun("s.x = x; s.x()");
   23722           5 :     CHECK(!try_catch.HasCaught());
   23723          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23724             :   }
   23725             :   {
   23726           5 :     TryCatch try_catch(isolate);
   23727             :     auto result = CompileRun("x.call(s)");
   23728           5 :     CHECK(!try_catch.HasCaught());
   23729          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23730           5 :   }
   23731           5 : }
   23732             : 
   23733             : 
   23734       25880 : TEST(ChainSignatureCheck) {
   23735           5 :   LocalContext context;
   23736           5 :   auto isolate = context->GetIsolate();
   23737          10 :   v8::HandleScope scope(isolate);
   23738           5 :   auto global = context->Global();
   23739           5 :   auto sig_obj = FunctionTemplate::New(isolate);
   23740           5 :   auto sig = v8::Signature::New(isolate, sig_obj);
   23741          25 :   for (int i = 0; i < 4; ++i) {
   23742          20 :     auto temp = FunctionTemplate::New(isolate);
   23743          20 :     temp->Inherit(sig_obj);
   23744             :     sig_obj = temp;
   23745             :   }
   23746           5 :   auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
   23747             :   global->Set(context.local(), v8_str("sig_obj"),
   23748          20 :               sig_obj->GetFunction(context.local()).ToLocalChecked())
   23749          10 :       .FromJust();
   23750             :   global->Set(context.local(), v8_str("x"),
   23751          25 :               x->GetFunction(context.local()).ToLocalChecked())
   23752          10 :       .FromJust();
   23753             :   CompileRun("var s = new sig_obj();");
   23754             :   {
   23755           5 :     TryCatch try_catch(isolate);
   23756             :     CompileRun("x()");
   23757           5 :     CHECK(try_catch.HasCaught());
   23758             :   }
   23759             :   {
   23760           5 :     TryCatch try_catch(isolate);
   23761             :     CompileRun("x.call(1)");
   23762           5 :     CHECK(try_catch.HasCaught());
   23763             :   }
   23764             :   {
   23765           5 :     TryCatch try_catch(isolate);
   23766             :     auto result = CompileRun("s.x = x; s.x()");
   23767           5 :     CHECK(!try_catch.HasCaught());
   23768          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23769             :   }
   23770             :   {
   23771           5 :     TryCatch try_catch(isolate);
   23772             :     auto result = CompileRun("x.call(s)");
   23773           5 :     CHECK(!try_catch.HasCaught());
   23774          10 :     CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
   23775           5 :   }
   23776           5 : }
   23777             : 
   23778             : 
   23779             : static const char* last_event_message;
   23780             : static int last_event_status;
   23781          10 : void StoringEventLoggerCallback(const char* message, int status) {
   23782          10 :     last_event_message = message;
   23783          10 :     last_event_status = status;
   23784          10 : }
   23785             : 
   23786             : 
   23787       25880 : TEST(EventLogging) {
   23788           5 :   v8::Isolate* isolate = CcTest::isolate();
   23789           5 :   isolate->SetEventLogger(StoringEventLoggerCallback);
   23790             :   v8::internal::HistogramTimer histogramTimer(
   23791             :       "V8.Test", 0, 10000, v8::internal::HistogramTimerResolution::MILLISECOND,
   23792             :       50, reinterpret_cast<v8::internal::Isolate*>(isolate)->counters());
   23793             :   histogramTimer.Start();
   23794           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   23795           5 :   CHECK_EQ(0, last_event_status);
   23796             :   histogramTimer.Stop();
   23797           5 :   CHECK_EQ(0, strcmp("V8.Test", last_event_message));
   23798           5 :   CHECK_EQ(1, last_event_status);
   23799           5 : }
   23800             : 
   23801       25880 : TEST(PropertyDescriptor) {
   23802           5 :   LocalContext context;
   23803           5 :   v8::Isolate* isolate = context->GetIsolate();
   23804          10 :   v8::HandleScope scope(isolate);
   23805             : 
   23806             :   {  // empty descriptor
   23807           5 :     v8::PropertyDescriptor desc;
   23808           5 :     CHECK(!desc.has_value());
   23809           5 :     CHECK(!desc.has_set());
   23810           5 :     CHECK(!desc.has_get());
   23811           5 :     CHECK(!desc.has_enumerable());
   23812           5 :     CHECK(!desc.has_configurable());
   23813           5 :     CHECK(!desc.has_writable());
   23814             :   }
   23815             :   {
   23816             :     // data descriptor
   23817           5 :     v8::PropertyDescriptor desc(v8_num(42));
   23818           5 :     desc.set_enumerable(false);
   23819          10 :     CHECK(desc.value() == v8_num(42));
   23820           5 :     CHECK(desc.has_value());
   23821           5 :     CHECK(!desc.has_set());
   23822           5 :     CHECK(!desc.has_get());
   23823           5 :     CHECK(desc.has_enumerable());
   23824           5 :     CHECK(!desc.enumerable());
   23825           5 :     CHECK(!desc.has_configurable());
   23826           5 :     CHECK(!desc.has_writable());
   23827             :   }
   23828             :   {
   23829             :     // data descriptor
   23830           5 :     v8::PropertyDescriptor desc(v8_num(42));
   23831           5 :     desc.set_configurable(true);
   23832          10 :     CHECK(desc.value() == v8_num(42));
   23833           5 :     CHECK(desc.has_value());
   23834           5 :     CHECK(!desc.has_set());
   23835           5 :     CHECK(!desc.has_get());
   23836           5 :     CHECK(desc.has_configurable());
   23837           5 :     CHECK(desc.configurable());
   23838           5 :     CHECK(!desc.has_enumerable());
   23839           5 :     CHECK(!desc.has_writable());
   23840             :   }
   23841             :   {
   23842             :     // data descriptor
   23843           5 :     v8::PropertyDescriptor desc(v8_num(42));
   23844           5 :     desc.set_configurable(false);
   23845          10 :     CHECK(desc.value() == v8_num(42));
   23846           5 :     CHECK(desc.has_value());
   23847           5 :     CHECK(!desc.has_set());
   23848           5 :     CHECK(!desc.has_get());
   23849           5 :     CHECK(desc.has_configurable());
   23850           5 :     CHECK(!desc.configurable());
   23851           5 :     CHECK(!desc.has_enumerable());
   23852           5 :     CHECK(!desc.has_writable());
   23853             :   }
   23854             :   {
   23855             :     // data descriptor
   23856           5 :     v8::PropertyDescriptor desc(v8_num(42), false);
   23857          10 :     CHECK(desc.value() == v8_num(42));
   23858           5 :     CHECK(desc.has_value());
   23859           5 :     CHECK(!desc.has_set());
   23860           5 :     CHECK(!desc.has_get());
   23861           5 :     CHECK(!desc.has_enumerable());
   23862           5 :     CHECK(!desc.has_configurable());
   23863           5 :     CHECK(desc.has_writable());
   23864           5 :     CHECK(!desc.writable());
   23865             :   }
   23866             :   {
   23867             :     // data descriptor
   23868           5 :     v8::PropertyDescriptor desc(v8::Local<v8::Value>(), true);
   23869           5 :     CHECK(!desc.has_value());
   23870           5 :     CHECK(!desc.has_set());
   23871           5 :     CHECK(!desc.has_get());
   23872           5 :     CHECK(!desc.has_enumerable());
   23873           5 :     CHECK(!desc.has_configurable());
   23874           5 :     CHECK(desc.has_writable());
   23875           5 :     CHECK(desc.writable());
   23876             :   }
   23877             :   {
   23878             :     // accessor descriptor
   23879             :     CompileRun("var set = function() {return 43;};");
   23880             : 
   23881             :     v8::Local<v8::Function> set =
   23882             :         v8::Local<v8::Function>::Cast(context->Global()
   23883          20 :                                           ->Get(context.local(), v8_str("set"))
   23884           5 :                                           .ToLocalChecked());
   23885           5 :     v8::PropertyDescriptor desc(v8::Undefined(isolate), set);
   23886           5 :     desc.set_configurable(false);
   23887           5 :     CHECK(!desc.has_value());
   23888           5 :     CHECK(desc.has_get());
   23889          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   23890           5 :     CHECK(desc.has_set());
   23891          10 :     CHECK(desc.set() == set);
   23892           5 :     CHECK(!desc.has_enumerable());
   23893           5 :     CHECK(desc.has_configurable());
   23894           5 :     CHECK(!desc.configurable());
   23895           5 :     CHECK(!desc.has_writable());
   23896             :   }
   23897             :   {
   23898             :     // accessor descriptor with Proxy
   23899             :     CompileRun(
   23900             :         "var set = new Proxy(function() {}, {});"
   23901             :         "var get = undefined;");
   23902             : 
   23903             :     v8::Local<v8::Value> get =
   23904             :         v8::Local<v8::Value>::Cast(context->Global()
   23905          20 :                                        ->Get(context.local(), v8_str("get"))
   23906          10 :                                        .ToLocalChecked());
   23907             :     v8::Local<v8::Function> set =
   23908             :         v8::Local<v8::Function>::Cast(context->Global()
   23909          20 :                                           ->Get(context.local(), v8_str("set"))
   23910           5 :                                           .ToLocalChecked());
   23911           5 :     v8::PropertyDescriptor desc(get, set);
   23912           5 :     desc.set_configurable(false);
   23913           5 :     CHECK(!desc.has_value());
   23914          10 :     CHECK(desc.get() == v8::Undefined(isolate));
   23915           5 :     CHECK(desc.has_get());
   23916          10 :     CHECK(desc.set() == set);
   23917           5 :     CHECK(desc.has_set());
   23918           5 :     CHECK(!desc.has_enumerable());
   23919           5 :     CHECK(desc.has_configurable());
   23920           5 :     CHECK(!desc.configurable());
   23921           5 :     CHECK(!desc.has_writable());
   23922             :   }
   23923             :   {
   23924             :     // accessor descriptor with empty function handle
   23925             :     v8::Local<v8::Function> get = v8::Local<v8::Function>();
   23926           5 :     v8::PropertyDescriptor desc(get, get);
   23927           5 :     CHECK(!desc.has_value());
   23928           5 :     CHECK(!desc.has_get());
   23929           5 :     CHECK(!desc.has_set());
   23930           5 :     CHECK(!desc.has_enumerable());
   23931           5 :     CHECK(!desc.has_configurable());
   23932           5 :     CHECK(!desc.has_writable());
   23933           5 :   }
   23934           5 : }
   23935             : 
   23936       25880 : TEST(Promises) {
   23937           5 :   LocalContext context;
   23938           5 :   v8::Isolate* isolate = context->GetIsolate();
   23939          10 :   v8::HandleScope scope(isolate);
   23940             : 
   23941             :   // Creation.
   23942             :   Local<v8::Promise::Resolver> pr =
   23943           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23944             :   Local<v8::Promise::Resolver> rr =
   23945           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23946           5 :   Local<v8::Promise> p = pr->GetPromise();
   23947           5 :   Local<v8::Promise> r = rr->GetPromise();
   23948             : 
   23949             :   // IsPromise predicate.
   23950           5 :   CHECK(p->IsPromise());
   23951           5 :   CHECK(r->IsPromise());
   23952           5 :   Local<Value> o = v8::Object::New(isolate);
   23953           5 :   CHECK(!o->IsPromise());
   23954             : 
   23955             :   // Resolution and rejection.
   23956          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   23957           5 :   CHECK(p->IsPromise());
   23958          15 :   rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
   23959          10 :   CHECK(r->IsPromise());
   23960           5 : }
   23961             : 
   23962             : // Promise.Then(on_fulfilled)
   23963       25880 : TEST(PromiseThen) {
   23964           5 :   LocalContext context;
   23965           5 :   v8::Isolate* isolate = context->GetIsolate();
   23966           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   23967          10 :   v8::HandleScope scope(isolate);
   23968           5 :   Local<Object> global = context->Global();
   23969             : 
   23970             :   // Creation.
   23971             :   Local<v8::Promise::Resolver> pr =
   23972           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23973             :   Local<v8::Promise::Resolver> qr =
   23974           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   23975           5 :   Local<v8::Promise> p = pr->GetPromise();
   23976           5 :   Local<v8::Promise> q = qr->GetPromise();
   23977             : 
   23978           5 :   CHECK(p->IsPromise());
   23979           5 :   CHECK(q->IsPromise());
   23980             : 
   23981          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   23982          10 :   qr->Resolve(context.local(), p).FromJust();
   23983             : 
   23984             :   // Chaining non-pending promises.
   23985             :   CompileRun(
   23986             :       "var x1 = 0;\n"
   23987             :       "var x2 = 0;\n"
   23988             :       "function f1(x) { x1 = x; return x+1 };\n"
   23989             :       "function f2(x) { x2 = x; return x+1 };\n");
   23990             :   Local<Function> f1 = Local<Function>::Cast(
   23991          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   23992             :   Local<Function> f2 = Local<Function>::Cast(
   23993          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   23994             : 
   23995             :   // Then
   23996             :   CompileRun("x1 = x2 = 0;");
   23997           5 :   q->Then(context.local(), f1).ToLocalChecked();
   23998          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   23999             :                   .ToLocalChecked()
   24000             :                   ->Int32Value(context.local())
   24001             :                   .FromJust());
   24002           5 :   isolate->RunMicrotasks();
   24003          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24004             :                   .ToLocalChecked()
   24005             :                   ->Int32Value(context.local())
   24006             :                   .FromJust());
   24007             : 
   24008             :   // Then
   24009             :   CompileRun("x1 = x2 = 0;");
   24010           5 :   pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24011           5 :   qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24012             : 
   24013          10 :   qr->Resolve(context.local(), pr).FromJust();
   24014             :   qr->GetPromise()
   24015          10 :       ->Then(context.local(), f1)
   24016           5 :       .ToLocalChecked()
   24017           5 :       ->Then(context.local(), f2)
   24018           5 :       .ToLocalChecked();
   24019             : 
   24020          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24021             :                   .ToLocalChecked()
   24022             :                   ->Int32Value(context.local())
   24023             :                   .FromJust());
   24024          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24025             :                   .ToLocalChecked()
   24026             :                   ->Int32Value(context.local())
   24027             :                   .FromJust());
   24028           5 :   isolate->RunMicrotasks();
   24029          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24030             :                   .ToLocalChecked()
   24031             :                   ->Int32Value(context.local())
   24032             :                   .FromJust());
   24033          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24034             :                   .ToLocalChecked()
   24035             :                   ->Int32Value(context.local())
   24036             :                   .FromJust());
   24037             : 
   24038          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
   24039             : 
   24040          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24041             :                   .ToLocalChecked()
   24042             :                   ->Int32Value(context.local())
   24043             :                   .FromJust());
   24044          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24045             :                   .ToLocalChecked()
   24046             :                   ->Int32Value(context.local())
   24047             :                   .FromJust());
   24048           5 :   isolate->RunMicrotasks();
   24049          20 :   CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
   24050             :                   .ToLocalChecked()
   24051             :                   ->Int32Value(context.local())
   24052             :                   .FromJust());
   24053          20 :   CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
   24054             :                   .ToLocalChecked()
   24055             :                   ->Int32Value(context.local())
   24056           5 :                   .FromJust());
   24057           5 : }
   24058             : 
   24059             : // Promise.Then(on_fulfilled, on_rejected)
   24060       25880 : TEST(PromiseThen2) {
   24061           5 :   LocalContext context;
   24062           5 :   v8::Isolate* isolate = context->GetIsolate();
   24063           5 :   isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
   24064          10 :   v8::HandleScope scope(isolate);
   24065           5 :   Local<Object> global = context->Global();
   24066             : 
   24067             :   // Creation.
   24068             :   Local<v8::Promise::Resolver> pr =
   24069           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24070           5 :   Local<v8::Promise> p = pr->GetPromise();
   24071             : 
   24072           5 :   CHECK(p->IsPromise());
   24073             : 
   24074          15 :   pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
   24075             : 
   24076             :   // Chaining non-pending promises.
   24077             :   CompileRun(
   24078             :       "var x1 = 0;\n"
   24079             :       "var x2 = 0;\n"
   24080             :       "function f1(x) { x1 = x; return x+1 };\n"
   24081             :       "function f2(x) { x2 = x; return x+1 };\n"
   24082             :       "function f3(x) { throw x + 100 };\n");
   24083             :   Local<Function> f1 = Local<Function>::Cast(
   24084          15 :       global->Get(context.local(), v8_str("f1")).ToLocalChecked());
   24085             :   Local<Function> f2 = Local<Function>::Cast(
   24086          15 :       global->Get(context.local(), v8_str("f2")).ToLocalChecked());
   24087             :   Local<Function> f3 = Local<Function>::Cast(
   24088          15 :       global->Get(context.local(), v8_str("f3")).ToLocalChecked());
   24089             : 
   24090             :   // Then
   24091             :   CompileRun("x1 = x2 = 0;");
   24092           5 :   Local<v8::Promise> a = p->Then(context.local(), f1, f2).ToLocalChecked();
   24093          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
   24094             :                   .ToLocalChecked()
   24095             :                   ->Int32Value(context.local())
   24096             :                   .FromJust());
   24097           5 :   isolate->RunMicrotasks();
   24098          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24099             :                   .ToLocalChecked()
   24100             :                   ->Int32Value(context.local())
   24101             :                   .FromJust());
   24102          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24103             :                   .ToLocalChecked()
   24104             :                   ->Int32Value(context.local())
   24105             :                   .FromJust());
   24106             : 
   24107           5 :   Local<v8::Promise> b = a->Then(context.local(), f3, f2).ToLocalChecked();
   24108           5 :   isolate->RunMicrotasks();
   24109          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24110             :                   .ToLocalChecked()
   24111             :                   ->Int32Value(context.local())
   24112             :                   .FromJust());
   24113          20 :   CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
   24114             :                   .ToLocalChecked()
   24115             :                   ->Int32Value(context.local())
   24116             :                   .FromJust());
   24117             : 
   24118           5 :   Local<v8::Promise> c = b->Then(context.local(), f1, f2).ToLocalChecked();
   24119           5 :   isolate->RunMicrotasks();
   24120          20 :   CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
   24121             :                   .ToLocalChecked()
   24122             :                   ->Int32Value(context.local())
   24123             :                   .FromJust());
   24124          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24125             :                     .ToLocalChecked()
   24126             :                     ->Int32Value(context.local())
   24127             :                     .FromJust());
   24128             : 
   24129           5 :   v8::Local<v8::Promise> d = c->Then(context.local(), f1, f2).ToLocalChecked();
   24130           5 :   isolate->RunMicrotasks();
   24131          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24132             :                     .ToLocalChecked()
   24133             :                     ->Int32Value(context.local())
   24134             :                     .FromJust());
   24135          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24136             :                     .ToLocalChecked()
   24137             :                     ->Int32Value(context.local())
   24138             :                     .FromJust());
   24139             : 
   24140           5 :   v8::Local<v8::Promise> e = d->Then(context.local(), f3, f2).ToLocalChecked();
   24141           5 :   isolate->RunMicrotasks();
   24142          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24143             :                     .ToLocalChecked()
   24144             :                     ->Int32Value(context.local())
   24145             :                     .FromJust());
   24146          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24147             :                     .ToLocalChecked()
   24148             :                     ->Int32Value(context.local())
   24149             :                     .FromJust());
   24150             : 
   24151           5 :   v8::Local<v8::Promise> f = e->Then(context.local(), f1, f3).ToLocalChecked();
   24152           5 :   isolate->RunMicrotasks();
   24153          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24154             :                     .ToLocalChecked()
   24155             :                     ->Int32Value(context.local())
   24156             :                     .FromJust());
   24157          20 :   CHECK_EQ(102, global->Get(context.local(), v8_str("x2"))
   24158             :                     .ToLocalChecked()
   24159             :                     ->Int32Value(context.local())
   24160             :                     .FromJust());
   24161             : 
   24162           5 :   f->Then(context.local(), f1, f2).ToLocalChecked();
   24163           5 :   isolate->RunMicrotasks();
   24164          20 :   CHECK_EQ(103, global->Get(context.local(), v8_str("x1"))
   24165             :                     .ToLocalChecked()
   24166             :                     ->Int32Value(context.local())
   24167             :                     .FromJust());
   24168          20 :   CHECK_EQ(304, global->Get(context.local(), v8_str("x2"))
   24169             :                     .ToLocalChecked()
   24170             :                     ->Int32Value(context.local())
   24171           5 :                     .FromJust());
   24172           5 : }
   24173             : 
   24174       25880 : TEST(PromiseStateAndValue) {
   24175           5 :   LocalContext context;
   24176           5 :   v8::Isolate* isolate = context->GetIsolate();
   24177          10 :   v8::HandleScope scope(isolate);
   24178             :   v8::Local<v8::Value> result = CompileRun(
   24179             :       "var resolver;"
   24180             :       "new Promise((res, rej) => { resolver = res; })");
   24181             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(result);
   24182           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24183             : 
   24184             :   CompileRun("resolver('fulfilled')");
   24185           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24186          10 :   CHECK(v8_str("fulfilled")->SameValue(promise->Result()));
   24187             : 
   24188             :   result = CompileRun("Promise.reject('rejected')");
   24189             :   promise = v8::Local<v8::Promise>::Cast(result);
   24190           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24191          15 :   CHECK(v8_str("rejected")->SameValue(promise->Result()));
   24192           5 : }
   24193             : 
   24194       25880 : TEST(ResolvedPromiseReFulfill) {
   24195           5 :   LocalContext context;
   24196           5 :   v8::Isolate* isolate = context->GetIsolate();
   24197          10 :   v8::HandleScope scope(isolate);
   24198             :   v8::Local<v8::String> value1 =
   24199             :       v8::String::NewFromUtf8(isolate, "foo", v8::NewStringType::kNormal)
   24200           5 :           .ToLocalChecked();
   24201             :   v8::Local<v8::String> value2 =
   24202             :       v8::String::NewFromUtf8(isolate, "bar", v8::NewStringType::kNormal)
   24203           5 :           .ToLocalChecked();
   24204             : 
   24205             :   v8::Local<v8::Promise::Resolver> resolver =
   24206           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24207           5 :   v8::Local<v8::Promise> promise = resolver->GetPromise();
   24208           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24209             : 
   24210          10 :   resolver->Resolve(context.local(), value1).ToChecked();
   24211           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24212          10 :   CHECK_EQ(promise->Result(), value1);
   24213             : 
   24214             :   // This should be a no-op.
   24215          10 :   resolver->Resolve(context.local(), value2).ToChecked();
   24216           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24217          10 :   CHECK_EQ(promise->Result(), value1);
   24218             : 
   24219             :   // This should be a no-op.
   24220          10 :   resolver->Reject(context.local(), value2).ToChecked();
   24221           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kFulfilled);
   24222          15 :   CHECK_EQ(promise->Result(), value1);
   24223           5 : }
   24224             : 
   24225       25880 : TEST(RejectedPromiseReFulfill) {
   24226           5 :   LocalContext context;
   24227           5 :   v8::Isolate* isolate = context->GetIsolate();
   24228          10 :   v8::HandleScope scope(isolate);
   24229             :   v8::Local<v8::String> value1 =
   24230             :       v8::String::NewFromUtf8(isolate, "foo", v8::NewStringType::kNormal)
   24231           5 :           .ToLocalChecked();
   24232             :   v8::Local<v8::String> value2 =
   24233             :       v8::String::NewFromUtf8(isolate, "bar", v8::NewStringType::kNormal)
   24234           5 :           .ToLocalChecked();
   24235             : 
   24236             :   v8::Local<v8::Promise::Resolver> resolver =
   24237           5 :       v8::Promise::Resolver::New(context.local()).ToLocalChecked();
   24238           5 :   v8::Local<v8::Promise> promise = resolver->GetPromise();
   24239           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kPending);
   24240             : 
   24241          10 :   resolver->Reject(context.local(), value1).ToChecked();
   24242           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24243          10 :   CHECK_EQ(promise->Result(), value1);
   24244             : 
   24245             :   // This should be a no-op.
   24246          10 :   resolver->Reject(context.local(), value2).ToChecked();
   24247           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24248          10 :   CHECK_EQ(promise->Result(), value1);
   24249             : 
   24250             :   // This should be a no-op.
   24251          10 :   resolver->Resolve(context.local(), value2).ToChecked();
   24252           5 :   CHECK_EQ(promise->State(), v8::Promise::PromiseState::kRejected);
   24253          15 :   CHECK_EQ(promise->Result(), value1);
   24254           5 : }
   24255             : 
   24256       25875 : TEST(DisallowJavascriptExecutionScope) {
   24257           0 :   LocalContext context;
   24258           0 :   v8::Isolate* isolate = context->GetIsolate();
   24259           0 :   v8::HandleScope scope(isolate);
   24260             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   24261           0 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   24262           0 :   CompileRun("2+2");
   24263           0 : }
   24264             : 
   24265       25880 : TEST(AllowJavascriptExecutionScope) {
   24266           5 :   LocalContext context;
   24267           5 :   v8::Isolate* isolate = context->GetIsolate();
   24268          10 :   v8::HandleScope scope(isolate);
   24269             :   v8::Isolate::DisallowJavascriptExecutionScope no_js(
   24270          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
   24271             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24272          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   24273           5 :   { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
   24274           5 :     CompileRun("1+1");
   24275           5 :   }
   24276           5 : }
   24277             : 
   24278       25880 : TEST(ThrowOnJavascriptExecution) {
   24279           5 :   LocalContext context;
   24280           5 :   v8::Isolate* isolate = context->GetIsolate();
   24281          10 :   v8::HandleScope scope(isolate);
   24282          10 :   v8::TryCatch try_catch(isolate);
   24283             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24284          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
   24285             :   CompileRun("1+1");
   24286          10 :   CHECK(try_catch.HasCaught());
   24287           5 : }
   24288             : 
   24289             : namespace {
   24290             : 
   24291             : class MockPlatform : public TestPlatform {
   24292             :  public:
   24293          10 :   MockPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {
   24294             :     // Now that it's completely constructed, make this the current platform.
   24295           5 :     i::V8::SetPlatformForTesting(this);
   24296           5 :   }
   24297          10 :   ~MockPlatform() override { i::V8::SetPlatformForTesting(old_platform_); }
   24298             : 
   24299             :   bool dump_without_crashing_called() const {
   24300             :     return dump_without_crashing_called_;
   24301             :   }
   24302             : 
   24303           5 :   void DumpWithoutCrashing() override { dump_without_crashing_called_ = true; }
   24304             : 
   24305             :  private:
   24306             :   v8::Platform* old_platform_;
   24307             :   bool dump_without_crashing_called_ = false;
   24308             : };
   24309             : 
   24310             : }  // namespace
   24311             : 
   24312       25880 : TEST(DumpOnJavascriptExecution) {
   24313           5 :   MockPlatform platform;
   24314             : 
   24315          10 :   LocalContext context;
   24316           5 :   v8::Isolate* isolate = context->GetIsolate();
   24317          10 :   v8::HandleScope scope(isolate);
   24318             :   v8::Isolate::DisallowJavascriptExecutionScope throw_js(
   24319          10 :       isolate, v8::Isolate::DisallowJavascriptExecutionScope::DUMP_ON_FAILURE);
   24320           5 :   CHECK(!platform.dump_without_crashing_called());
   24321             :   CompileRun("1+1");
   24322          10 :   CHECK(platform.dump_without_crashing_called());
   24323           5 : }
   24324             : 
   24325       25880 : TEST(Regress354123) {
   24326           5 :   LocalContext current;
   24327           5 :   v8::Isolate* isolate = current->GetIsolate();
   24328          10 :   v8::HandleScope scope(isolate);
   24329             : 
   24330           5 :   v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
   24331           5 :   templ->SetAccessCheckCallback(AccessCounter);
   24332          30 :   CHECK(current->Global()
   24333             :             ->Set(current.local(), v8_str("friend"),
   24334             :                   templ->NewInstance(current.local()).ToLocalChecked())
   24335             :             .FromJust());
   24336             : 
   24337             :   // Test access using __proto__ from the prototype chain.
   24338           5 :   access_count = 0;
   24339             :   CompileRun("friend.__proto__ = {};");
   24340           5 :   CHECK_EQ(2, access_count);
   24341             :   CompileRun("friend.__proto__;");
   24342           5 :   CHECK_EQ(4, access_count);
   24343             : 
   24344             :   // Test access using __proto__ as a hijacked function (A).
   24345           5 :   access_count = 0;
   24346             :   CompileRun("var p = Object.prototype;"
   24347             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
   24348             :              "f.call(friend, {});");
   24349           5 :   CHECK_EQ(1, access_count);
   24350             :   CompileRun("var p = Object.prototype;"
   24351             :              "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
   24352             :              "f.call(friend);");
   24353           5 :   CHECK_EQ(2, access_count);
   24354             : 
   24355             :   // Test access using __proto__ as a hijacked function (B).
   24356           5 :   access_count = 0;
   24357             :   CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
   24358             :              "f.call(friend, {});");
   24359           5 :   CHECK_EQ(1, access_count);
   24360             :   CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
   24361             :              "f.call(friend);");
   24362           5 :   CHECK_EQ(2, access_count);
   24363             : 
   24364             :   // Test access using Object.setPrototypeOf reflective method.
   24365           5 :   access_count = 0;
   24366             :   CompileRun("Object.setPrototypeOf(friend, {});");
   24367           5 :   CHECK_EQ(1, access_count);
   24368             :   CompileRun("Object.getPrototypeOf(friend);");
   24369          10 :   CHECK_EQ(2, access_count);
   24370           5 : }
   24371             : 
   24372             : 
   24373       25880 : TEST(CaptureStackTraceForStackOverflow) {
   24374           5 :   v8::internal::FLAG_stack_size = 150;
   24375           5 :   LocalContext current;
   24376           5 :   v8::Isolate* isolate = current->GetIsolate();
   24377          10 :   v8::HandleScope scope(isolate);
   24378             :   isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
   24379           5 :                                                      v8::StackTrace::kDetailed);
   24380          10 :   v8::TryCatch try_catch(isolate);
   24381             :   CompileRun("(function f(x) { f(x+1); })(0)");
   24382          10 :   CHECK(try_catch.HasCaught());
   24383           5 : }
   24384             : 
   24385             : namespace {
   24386           5 : bool ValueEqualsString(v8::Isolate* isolate, Local<Value> lhs,
   24387             :                        const char* rhs) {
   24388           5 :   CHECK(!lhs.IsEmpty());
   24389           5 :   CHECK(lhs->IsString());
   24390           5 :   String::Utf8Value utf8_lhs(isolate, lhs);
   24391           5 :   return strcmp(rhs, *utf8_lhs) == 0;
   24392             : }
   24393             : }  // namespace
   24394             : 
   24395       25880 : TEST(ScriptNameAndLineNumber) {
   24396           5 :   LocalContext env;
   24397           5 :   v8::Isolate* isolate = env->GetIsolate();
   24398          10 :   v8::HandleScope scope(isolate);
   24399             :   const char* url = "http://www.foo.com/foo.js";
   24400           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   24401           5 :   v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
   24402             : 
   24403             :   Local<Script> script =
   24404           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   24405          10 :   CHECK(ValueEqualsString(isolate, script->GetUnboundScript()->GetScriptName(),
   24406             :                           url));
   24407             : 
   24408          10 :   int line_number = script->GetUnboundScript()->GetLineNumber(0);
   24409          10 :   CHECK_EQ(13, line_number);
   24410           5 : }
   24411             : 
   24412       25880 : TEST(ScriptPositionInfo) {
   24413           5 :   LocalContext env;
   24414           5 :   v8::Isolate* isolate = env->GetIsolate();
   24415             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   24416          10 :   v8::HandleScope scope(isolate);
   24417             :   const char* url = "http://www.foo.com/foo.js";
   24418           5 :   v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
   24419             :   v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
   24420             :                                                   "var bar;\n"
   24421             :                                                   "var fisk = foo + bar;\n"),
   24422           5 :                                            origin);
   24423             :   Local<Script> script =
   24424           5 :       v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
   24425             : 
   24426             :   i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
   24427          10 :       v8::Utils::OpenHandle(*script->GetUnboundScript()));
   24428          10 :   CHECK(obj->script()->IsScript());
   24429             : 
   24430          10 :   i::Handle<i::Script> script1(i::Script::cast(obj->script()), i_isolate);
   24431             : 
   24432             :   v8::internal::Script::PositionInfo info;
   24433             : 
   24434          15 :   for (int i = 0; i < 2; ++i) {
   24435             :     // With offset.
   24436             : 
   24437             :     // Behave as if 0 was passed if position is negative.
   24438          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
   24439          10 :     CHECK_EQ(13, info.line);
   24440          10 :     CHECK_EQ(0, info.column);
   24441          10 :     CHECK_EQ(0, info.line_start);
   24442          10 :     CHECK_EQ(8, info.line_end);
   24443             : 
   24444          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
   24445          10 :     CHECK_EQ(13, info.line);
   24446          10 :     CHECK_EQ(0, info.column);
   24447          10 :     CHECK_EQ(0, info.line_start);
   24448          10 :     CHECK_EQ(8, info.line_end);
   24449             : 
   24450          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
   24451          10 :     CHECK_EQ(13, info.line);
   24452          10 :     CHECK_EQ(8, info.column);
   24453          10 :     CHECK_EQ(0, info.line_start);
   24454          10 :     CHECK_EQ(8, info.line_end);
   24455             : 
   24456          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
   24457          10 :     CHECK_EQ(14, info.line);
   24458          10 :     CHECK_EQ(0, info.column);
   24459          10 :     CHECK_EQ(9, info.line_start);
   24460          10 :     CHECK_EQ(17, info.line_end);
   24461             : 
   24462             :     // Fail when position is larger than script size.
   24463          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
   24464             : 
   24465             :     // Without offset.
   24466             : 
   24467             :     // Behave as if 0 was passed if position is negative.
   24468          10 :     CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
   24469          10 :     CHECK_EQ(0, info.line);
   24470          10 :     CHECK_EQ(0, info.column);
   24471          10 :     CHECK_EQ(0, info.line_start);
   24472          10 :     CHECK_EQ(8, info.line_end);
   24473             : 
   24474          10 :     CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
   24475          10 :     CHECK_EQ(0, info.line);
   24476          10 :     CHECK_EQ(0, info.column);
   24477          10 :     CHECK_EQ(0, info.line_start);
   24478          10 :     CHECK_EQ(8, info.line_end);
   24479             : 
   24480          10 :     CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
   24481          10 :     CHECK_EQ(0, info.line);
   24482          10 :     CHECK_EQ(8, info.column);
   24483          10 :     CHECK_EQ(0, info.line_start);
   24484          10 :     CHECK_EQ(8, info.line_end);
   24485             : 
   24486          10 :     CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
   24487          10 :     CHECK_EQ(1, info.line);
   24488          10 :     CHECK_EQ(0, info.column);
   24489          10 :     CHECK_EQ(9, info.line_start);
   24490          10 :     CHECK_EQ(17, info.line_end);
   24491             : 
   24492             :     // Fail when position is larger than script size.
   24493          10 :     CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
   24494             : 
   24495          10 :     i::Script::InitLineEnds(script1);
   24496           5 :   }
   24497           5 : }
   24498             : 
   24499         155 : void CheckMagicComments(v8::Isolate* isolate, Local<Script> script,
   24500             :                         const char* expected_source_url,
   24501             :                         const char* expected_source_mapping_url) {
   24502         155 :   if (expected_source_url != nullptr) {
   24503             :     v8::String::Utf8Value url(isolate,
   24504          70 :                               script->GetUnboundScript()->GetSourceURL());
   24505          35 :     CHECK_EQ(0, strcmp(expected_source_url, *url));
   24506             :   } else {
   24507         360 :     CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
   24508             :   }
   24509         155 :   if (expected_source_mapping_url != nullptr) {
   24510             :     v8::String::Utf8Value url(
   24511          60 :         isolate, script->GetUnboundScript()->GetSourceMappingURL());
   24512          30 :     CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
   24513             :   } else {
   24514         375 :     CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
   24515             :   }
   24516         155 : }
   24517             : 
   24518          70 : void SourceURLHelper(v8::Isolate* isolate, const char* source,
   24519             :                      const char* expected_source_url,
   24520             :                      const char* expected_source_mapping_url) {
   24521          70 :   Local<Script> script = v8_compile(source);
   24522             :   CheckMagicComments(isolate, script, expected_source_url,
   24523          70 :                      expected_source_mapping_url);
   24524          70 : }
   24525             : 
   24526             : 
   24527       25880 : TEST(ScriptSourceURLAndSourceMappingURL) {
   24528           5 :   LocalContext env;
   24529           5 :   v8::Isolate* isolate = env->GetIsolate();
   24530          10 :   v8::HandleScope scope(isolate);
   24531             :   SourceURLHelper(isolate,
   24532             :                   "function foo() {}\n"
   24533             :                   "//# sourceURL=bar1.js\n",
   24534           5 :                   "bar1.js", nullptr);
   24535             :   SourceURLHelper(isolate,
   24536             :                   "function foo() {}\n"
   24537             :                   "//# sourceMappingURL=bar2.js\n",
   24538           5 :                   nullptr, "bar2.js");
   24539             : 
   24540             :   // Both sourceURL and sourceMappingURL.
   24541             :   SourceURLHelper(isolate,
   24542             :                   "function foo() {}\n"
   24543             :                   "//# sourceURL=bar3.js\n"
   24544             :                   "//# sourceMappingURL=bar4.js\n",
   24545           5 :                   "bar3.js", "bar4.js");
   24546             : 
   24547             :   // Two source URLs; the first one is ignored.
   24548             :   SourceURLHelper(isolate,
   24549             :                   "function foo() {}\n"
   24550             :                   "//# sourceURL=ignoreme.js\n"
   24551             :                   "//# sourceURL=bar5.js\n",
   24552           5 :                   "bar5.js", nullptr);
   24553             :   SourceURLHelper(isolate,
   24554             :                   "function foo() {}\n"
   24555             :                   "//# sourceMappingURL=ignoreme.js\n"
   24556             :                   "//# sourceMappingURL=bar6.js\n",
   24557           5 :                   nullptr, "bar6.js");
   24558             : 
   24559             :   // SourceURL or sourceMappingURL in the middle of the script.
   24560             :   SourceURLHelper(isolate,
   24561             :                   "function foo() {}\n"
   24562             :                   "//# sourceURL=bar7.js\n"
   24563             :                   "function baz() {}\n",
   24564           5 :                   "bar7.js", nullptr);
   24565             :   SourceURLHelper(isolate,
   24566             :                   "function foo() {}\n"
   24567             :                   "//# sourceMappingURL=bar8.js\n"
   24568             :                   "function baz() {}\n",
   24569           5 :                   nullptr, "bar8.js");
   24570             : 
   24571             :   // Too much whitespace.
   24572             :   SourceURLHelper(isolate,
   24573             :                   "function foo() {}\n"
   24574             :                   "//#  sourceURL=bar9.js\n"
   24575             :                   "//#  sourceMappingURL=bar10.js\n",
   24576           5 :                   nullptr, nullptr);
   24577             :   SourceURLHelper(isolate,
   24578             :                   "function foo() {}\n"
   24579             :                   "//# sourceURL =bar11.js\n"
   24580             :                   "//# sourceMappingURL =bar12.js\n",
   24581           5 :                   nullptr, nullptr);
   24582             : 
   24583             :   // Disallowed characters in value.
   24584             :   SourceURLHelper(isolate,
   24585             :                   "function foo() {}\n"
   24586             :                   "//# sourceURL=bar13 .js   \n"
   24587             :                   "//# sourceMappingURL=bar14 .js \n",
   24588           5 :                   nullptr, nullptr);
   24589             :   SourceURLHelper(isolate,
   24590             :                   "function foo() {}\n"
   24591             :                   "//# sourceURL=bar15\t.js   \n"
   24592             :                   "//# sourceMappingURL=bar16\t.js \n",
   24593           5 :                   nullptr, nullptr);
   24594             :   SourceURLHelper(isolate,
   24595             :                   "function foo() {}\n"
   24596             :                   "//# sourceURL=bar17'.js   \n"
   24597             :                   "//# sourceMappingURL=bar18'.js \n",
   24598           5 :                   nullptr, nullptr);
   24599             :   SourceURLHelper(isolate,
   24600             :                   "function foo() {}\n"
   24601             :                   "//# sourceURL=bar19\".js   \n"
   24602             :                   "//# sourceMappingURL=bar20\".js \n",
   24603           5 :                   nullptr, nullptr);
   24604             : 
   24605             :   // Not too much whitespace.
   24606             :   SourceURLHelper(isolate,
   24607             :                   "function foo() {}\n"
   24608             :                   "//# sourceURL=  bar21.js   \n"
   24609             :                   "//# sourceMappingURL=  bar22.js \n",
   24610          10 :                   "bar21.js", "bar22.js");
   24611           5 : }
   24612             : 
   24613             : 
   24614       25880 : TEST(GetOwnPropertyDescriptor) {
   24615           5 :   LocalContext env;
   24616           5 :   v8::Isolate* isolate = env->GetIsolate();
   24617          10 :   v8::HandleScope scope(isolate);
   24618             :   CompileRun(
   24619             :       "var x = { value : 13};"
   24620             :       "Object.defineProperty(x, 'p0', {value : 12});"
   24621             :       "Object.defineProperty(x, Symbol.toStringTag, {value: 'foo'});"
   24622             :       "Object.defineProperty(x, 'p1', {"
   24623             :       "  set : function(value) { this.value = value; },"
   24624             :       "  get : function() { return this.value; },"
   24625             :       "});");
   24626             :   Local<Object> x = Local<Object>::Cast(
   24627          25 :       env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
   24628             :   Local<Value> desc =
   24629          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
   24630           5 :           .ToLocalChecked();
   24631           5 :   CHECK(desc->IsUndefined());
   24632             :   desc =
   24633          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
   24634          25 :   CHECK(v8_num(12)
   24635             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   24636             :                                       ->Get(env.local(), v8_str("value"))
   24637             :                                       .ToLocalChecked())
   24638             :             .FromJust());
   24639             :   desc =
   24640          15 :       x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
   24641             :   Local<Function> set =
   24642             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   24643          15 :                                 ->Get(env.local(), v8_str("set"))
   24644           5 :                                 .ToLocalChecked());
   24645             :   Local<Function> get =
   24646             :       Local<Function>::Cast(Local<Object>::Cast(desc)
   24647          15 :                                 ->Get(env.local(), v8_str("get"))
   24648           5 :                                 .ToLocalChecked());
   24649          20 :   CHECK(v8_num(13)
   24650             :             ->Equals(env.local(),
   24651             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   24652             :             .FromJust());
   24653           5 :   Local<Value> args[] = {v8_num(14)};
   24654          10 :   set->Call(env.local(), x, 1, args).ToLocalChecked();
   24655          20 :   CHECK(v8_num(14)
   24656             :             ->Equals(env.local(),
   24657             :                      get->Call(env.local(), x, 0, nullptr).ToLocalChecked())
   24658             :             .FromJust());
   24659             :   desc =
   24660          15 :       x->GetOwnPropertyDescriptor(env.local(), Symbol::GetToStringTag(isolate))
   24661           5 :           .ToLocalChecked();
   24662          25 :   CHECK(v8_str("foo")
   24663             :             ->Equals(env.local(), Local<Object>::Cast(desc)
   24664             :                                       ->Get(env.local(), v8_str("value"))
   24665             :                                       .ToLocalChecked())
   24666           5 :             .FromJust());
   24667           5 : }
   24668             : 
   24669             : 
   24670       25880 : TEST(Regress411877) {
   24671           5 :   v8::Isolate* isolate = CcTest::isolate();
   24672           5 :   v8::HandleScope handle_scope(isolate);
   24673             :   v8::Local<v8::ObjectTemplate> object_template =
   24674           5 :       v8::ObjectTemplate::New(isolate);
   24675           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24676             : 
   24677           5 :   v8::Local<Context> context = Context::New(isolate);
   24678             :   v8::Context::Scope context_scope(context);
   24679             : 
   24680          25 :   CHECK(context->Global()
   24681             :             ->Set(context, v8_str("o"),
   24682             :                   object_template->NewInstance(context).ToLocalChecked())
   24683             :             .FromJust());
   24684           5 :   CompileRun("Object.getOwnPropertyNames(o)");
   24685           5 : }
   24686             : 
   24687             : 
   24688       25880 : TEST(GetHiddenPropertyTableAfterAccessCheck) {
   24689           5 :   v8::Isolate* isolate = CcTest::isolate();
   24690           5 :   v8::HandleScope handle_scope(isolate);
   24691             :   v8::Local<v8::ObjectTemplate> object_template =
   24692           5 :       v8::ObjectTemplate::New(isolate);
   24693           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24694             : 
   24695           5 :   v8::Local<Context> context = Context::New(isolate);
   24696             :   v8::Context::Scope context_scope(context);
   24697             : 
   24698             :   v8::Local<v8::Object> obj =
   24699           5 :       object_template->NewInstance(context).ToLocalChecked();
   24700          20 :   obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
   24701          15 :   obj->Delete(context, v8_str("key")).FromJust();
   24702             : 
   24703             :   obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
   24704          15 :                   v8_str("hidden value 2"))
   24705          15 :       .FromJust();
   24706           5 : }
   24707             : 
   24708             : 
   24709       25880 : TEST(Regress411793) {
   24710           5 :   v8::Isolate* isolate = CcTest::isolate();
   24711           5 :   v8::HandleScope handle_scope(isolate);
   24712             :   v8::Local<v8::ObjectTemplate> object_template =
   24713           5 :       v8::ObjectTemplate::New(isolate);
   24714           5 :   object_template->SetAccessCheckCallback(AccessCounter);
   24715             : 
   24716           5 :   v8::Local<Context> context = Context::New(isolate);
   24717             :   v8::Context::Scope context_scope(context);
   24718             : 
   24719          25 :   CHECK(context->Global()
   24720             :             ->Set(context, v8_str("o"),
   24721             :                   object_template->NewInstance(context).ToLocalChecked())
   24722             :             .FromJust());
   24723             :   CompileRun(
   24724             :       "Object.defineProperty(o, 'key', "
   24725           5 :       "    { get: function() {}, set: function() {} });");
   24726           5 : }
   24727             : 
   24728         210 : class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
   24729             :  public:
   24730         105 :   explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
   24731             : 
   24732         405 :   size_t GetMoreData(const uint8_t** src) override {
   24733             :     // Unlike in real use cases, this function will never block.
   24734         405 :     if (chunks_[index_] == nullptr) {
   24735             :       return 0;
   24736             :     }
   24737             :     // Copy the data, since the caller takes ownership of it.
   24738         310 :     size_t len = strlen(chunks_[index_]);
   24739             :     // We don't need to zero-terminate since we return the length.
   24740         310 :     uint8_t* copy = new uint8_t[len];
   24741         310 :     memcpy(copy, chunks_[index_], len);
   24742         310 :     *src = copy;
   24743         310 :     ++index_;
   24744         310 :     return len;
   24745             :   }
   24746             : 
   24747             :   // Helper for constructing a string from chunks (the compilation needs it
   24748             :   // too).
   24749         105 :   static char* FullSourceString(const char** chunks) {
   24750             :     size_t total_len = 0;
   24751         435 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   24752         330 :       total_len += strlen(chunks[i]);
   24753             :     }
   24754         105 :     char* full_string = new char[total_len + 1];
   24755             :     size_t offset = 0;
   24756         435 :     for (size_t i = 0; chunks[i] != nullptr; ++i) {
   24757         330 :       size_t len = strlen(chunks[i]);
   24758         330 :       memcpy(full_string + offset, chunks[i], len);
   24759         330 :       offset += len;
   24760             :     }
   24761         105 :     full_string[total_len] = 0;
   24762         105 :     return full_string;
   24763             :   }
   24764             : 
   24765             :  private:
   24766             :   const char** chunks_;
   24767             :   unsigned index_;
   24768             : };
   24769             : 
   24770             : 
   24771             : // Helper function for running streaming tests.
   24772          95 : void RunStreamingTest(const char** chunks,
   24773             :                       v8::ScriptCompiler::StreamedSource::Encoding encoding =
   24774             :                           v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   24775             :                       bool expected_success = true,
   24776             :                       const char* expected_source_url = nullptr,
   24777             :                       const char* expected_source_mapping_url = nullptr) {
   24778          95 :   LocalContext env;
   24779          95 :   v8::Isolate* isolate = env->GetIsolate();
   24780         190 :   v8::HandleScope scope(isolate);
   24781         190 :   v8::TryCatch try_catch(isolate);
   24782             : 
   24783             :   v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
   24784         285 :                                             encoding);
   24785             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   24786          95 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   24787             : 
   24788             :   // TestSourceStream::GetMoreData won't block, so it's OK to just run the
   24789             :   // task here in the main thread.
   24790          95 :   task->Run();
   24791          95 :   delete task;
   24792             : 
   24793             :   // Possible errors are only produced while compiling.
   24794          95 :   CHECK(!try_catch.HasCaught());
   24795             : 
   24796          95 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   24797          95 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   24798             :   v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
   24799          95 :       env.local(), &source, v8_str(full_source), origin);
   24800          95 :   if (expected_success) {
   24801          85 :     CHECK(!script.IsEmpty());
   24802             :     v8::Local<Value> result(
   24803         170 :         script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
   24804             :     // All scripts are supposed to return the fixed value 13 when ran.
   24805         170 :     CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
   24806             :     CheckMagicComments(isolate, script.ToLocalChecked(), expected_source_url,
   24807          85 :                        expected_source_mapping_url);
   24808             :   } else {
   24809          10 :     CHECK(script.IsEmpty());
   24810          10 :     CHECK(try_catch.HasCaught());
   24811             :   }
   24812         190 :   delete[] full_source;
   24813          95 : }
   24814             : 
   24815       25880 : TEST(StreamingSimpleScript) {
   24816             :   // This script is unrealistically small, since no one chunk is enough to fill
   24817             :   // the backing buffer of Scanner, let alone overflow it.
   24818             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
   24819           5 :                           nullptr};
   24820           5 :   RunStreamingTest(chunks);
   24821           5 : }
   24822             : 
   24823       25880 : TEST(StreamingScriptConstantArray) {
   24824             :   // When run with Ignition, tests that the streaming parser canonicalizes
   24825             :   // handles so that they are only added to the constant pool array once.
   24826             :   const char* chunks[] = {
   24827             :       "var a = {};",        "var b = {};", "var c = 'testing';",
   24828           5 :       "var d = 'testing';", "13;",         nullptr};
   24829           5 :   RunStreamingTest(chunks);
   24830           5 : }
   24831             : 
   24832       25880 : TEST(StreamingScriptEvalShadowing) {
   24833             :   // When run with Ignition, tests that the streaming parser canonicalizes
   24834             :   // handles so the Variable::is_possibly_eval() is correct.
   24835             :   const char* chunk1 =
   24836             :       "(function() {\n"
   24837             :       "  var y = 2;\n"
   24838             :       "  return (function() {\n"
   24839             :       "    eval('var y = 13;');\n"
   24840             :       "    function g() {\n"
   24841             :       "      return y\n"
   24842             :       "    }\n"
   24843             :       "    return g();\n"
   24844             :       "  })()\n"
   24845             :       "})()\n";
   24846           5 :   const char* chunks[] = {chunk1, nullptr};
   24847           5 :   RunStreamingTest(chunks);
   24848           5 : }
   24849             : 
   24850       25880 : TEST(StreamingBiggerScript) {
   24851             :   const char* chunk1 =
   24852             :       "function foo() {\n"
   24853             :       "  // Make this chunk sufficiently long so that it will overflow the\n"
   24854             :       "  // backing buffer of the Scanner.\n"
   24855             :       "  var i = 0;\n"
   24856             :       "  var result = 0;\n"
   24857             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24858             :       "  result = 0;\n"
   24859             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24860             :       "  result = 0;\n"
   24861             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24862             :       "  result = 0;\n"
   24863             :       "  for (i = 0; i < 13; ++i) { result = result + 1; }\n"
   24864             :       "  return result;\n"
   24865             :       "}\n";
   24866           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   24867           5 :   RunStreamingTest(chunks);
   24868           5 : }
   24869             : 
   24870             : 
   24871       25880 : TEST(StreamingScriptWithParseError) {
   24872             :   // Test that parse errors from streamed scripts are propagated correctly.
   24873             :   {
   24874             :     char chunk1[] =
   24875             :         "  // This will result in a parse error.\n"
   24876           5 :         "  var if else then foo";
   24877           5 :     char chunk2[] = "  13\n";
   24878           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   24879             : 
   24880             :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
   24881           5 :                      false);
   24882             :   }
   24883             :   // Test that the next script succeeds normally.
   24884             :   {
   24885             :     char chunk1[] =
   24886             :         "  // This will be parsed successfully.\n"
   24887           5 :         "  function foo() { return ";
   24888           5 :     char chunk2[] = "  13; }\n";
   24889           5 :     const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   24890             : 
   24891           5 :     RunStreamingTest(chunks);
   24892             :   }
   24893           5 : }
   24894             : 
   24895             : 
   24896       25880 : TEST(StreamingUtf8Script) {
   24897             :   // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
   24898             :   // don't like it.
   24899             :   const char* chunk1 =
   24900             :       "function foo() {\n"
   24901             :       "  // This function will contain an UTF-8 character which is not in\n"
   24902             :       "  // ASCII.\n"
   24903             :       "  var foob\xec\x92\x81r = 13;\n"
   24904             :       "  return foob\xec\x92\x81r;\n"
   24905             :       "}\n";
   24906           5 :   const char* chunks[] = {chunk1, "foo(); ", nullptr};
   24907           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24908           5 : }
   24909             : 
   24910             : 
   24911       25880 : TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
   24912             :   // A sanity check to prove that the approach of splitting UTF-8
   24913             :   // characters is correct. Here is an UTF-8 character which will take three
   24914             :   // bytes.
   24915             :   const char* reference = "\xec\x92\x81";
   24916             :   CHECK_EQ(3, strlen(reference));
   24917             : 
   24918             :   char chunk1[] =
   24919             :       "function foo() {\n"
   24920             :       "  // This function will contain an UTF-8 character which is not in\n"
   24921             :       "  // ASCII.\n"
   24922           5 :       "  var foob";
   24923             :   char chunk2[] =
   24924             :       "XXXr = 13;\n"
   24925             :       "  return foob\xec\x92\x81r;\n"
   24926           5 :       "}\n";
   24927          20 :   for (int i = 0; i < 3; ++i) {
   24928          15 :     chunk2[i] = reference[i];
   24929             :   }
   24930           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   24931           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24932           5 : }
   24933             : 
   24934             : 
   24935       25880 : TEST(StreamingUtf8ScriptWithSplitCharacters) {
   24936             :   // Stream data where a multi-byte UTF-8 character is split between two data
   24937             :   // chunks.
   24938             :   const char* reference = "\xec\x92\x81";
   24939             :   char chunk1[] =
   24940             :       "function foo() {\n"
   24941             :       "  // This function will contain an UTF-8 character which is not in\n"
   24942             :       "  // ASCII.\n"
   24943           5 :       "  var foobX";
   24944             :   char chunk2[] =
   24945             :       "XXr = 13;\n"
   24946             :       "  return foob\xec\x92\x81r;\n"
   24947           5 :       "}\n";
   24948           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   24949           5 :   chunk2[0] = reference[1];
   24950           5 :   chunk2[1] = reference[2];
   24951           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   24952           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24953           5 : }
   24954             : 
   24955             : 
   24956       25880 : TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
   24957             :   // Tests edge cases which should still be decoded correctly.
   24958             : 
   24959             :   // Case 1: a chunk contains only bytes for a split character (and no other
   24960             :   // data). This kind of a chunk would be exceptionally small, but we should
   24961             :   // still decode it correctly.
   24962             :   const char* reference = "\xec\x92\x81";
   24963             :   // The small chunk is at the beginning of the split character
   24964             :   {
   24965             :     char chunk1[] =
   24966             :         "function foo() {\n"
   24967             :         "  // This function will contain an UTF-8 character which is not in\n"
   24968             :         "  // ASCII.\n"
   24969           5 :         "  var foob";
   24970           5 :     char chunk2[] = "XX";
   24971             :     char chunk3[] =
   24972             :         "Xr = 13;\n"
   24973             :         "  return foob\xec\x92\x81r;\n"
   24974           5 :         "}\n";
   24975           5 :     chunk2[0] = reference[0];
   24976           5 :     chunk2[1] = reference[1];
   24977           5 :     chunk3[0] = reference[2];
   24978           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   24979           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24980             :   }
   24981             :   // The small chunk is at the end of a character
   24982             :   {
   24983             :     char chunk1[] =
   24984             :         "function foo() {\n"
   24985             :         "  // This function will contain an UTF-8 character which is not in\n"
   24986             :         "  // ASCII.\n"
   24987           5 :         "  var foobX";
   24988           5 :     char chunk2[] = "XX";
   24989             :     char chunk3[] =
   24990             :         "r = 13;\n"
   24991             :         "  return foob\xec\x92\x81r;\n"
   24992           5 :         "}\n";
   24993           5 :     chunk1[strlen(chunk1) - 1] = reference[0];
   24994           5 :     chunk2[0] = reference[1];
   24995           5 :     chunk2[1] = reference[2];
   24996           5 :     const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   24997           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   24998             :   }
   24999             :   // Case 2: the script ends with a multi-byte character. Make sure that it's
   25000             :   // decoded correctly and not just ignored.
   25001             :   {
   25002             :     char chunk1[] =
   25003             :         "var foob\xec\x92\x81 = 13;\n"
   25004           5 :         "foob\xec\x92\x81";
   25005           5 :     const char* chunks[] = {chunk1, nullptr};
   25006           5 :     RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25007             :   }
   25008           5 : }
   25009             : 
   25010             : 
   25011       25880 : TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
   25012             :   // Test cases where a UTF-8 character is split over several chunks. Those
   25013             :   // cases are not supported (the embedder should give the data in big enough
   25014             :   // chunks), but we shouldn't crash and parse this just fine.
   25015             :   const char* reference = "\xec\x92\x81";
   25016             :   char chunk1[] =
   25017             :       "function foo() {\n"
   25018             :       "  // This function will contain an UTF-8 character which is not in\n"
   25019             :       "  // ASCII.\n"
   25020           5 :       "  var foobX";
   25021           5 :   char chunk2[] = "X";
   25022             :   char chunk3[] =
   25023             :       "Xr = 13;\n"
   25024             :       "  return foob\xec\x92\x81r;\n"
   25025           5 :       "}\n";
   25026           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25027           5 :   chunk2[0] = reference[1];
   25028           5 :   chunk3[0] = reference[2];
   25029           5 :   const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", nullptr};
   25030             : 
   25031           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25032           5 : }
   25033             : 
   25034             : 
   25035             : 
   25036       25880 : TEST(StreamingWithDebuggingEnabledLate) {
   25037             :   // The streaming parser can only parse lazily, i.e. inner functions are not
   25038             :   // fully parsed. However, we may compile inner functions eagerly when
   25039             :   // debugging. Make sure that we can deal with this when turning on debugging
   25040             :   // after streaming parser has already finished parsing.
   25041             :   const char* chunks[] = {"with({x:1}) {",
   25042             :                           "  var foo = function foo(y) {",
   25043             :                           "    return x + y;",
   25044             :                           "  };",
   25045             :                           "  foo(2);",
   25046             :                           "}",
   25047           5 :                           nullptr};
   25048             : 
   25049           5 :   LocalContext env;
   25050           5 :   v8::Isolate* isolate = env->GetIsolate();
   25051          10 :   v8::HandleScope scope(isolate);
   25052          10 :   v8::TryCatch try_catch(isolate);
   25053             : 
   25054             :   v8::ScriptCompiler::StreamedSource source(
   25055             :       new TestSourceStream(chunks),
   25056          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25057             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25058           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25059             : 
   25060           5 :   task->Run();
   25061           5 :   delete task;
   25062             : 
   25063           5 :   CHECK(!try_catch.HasCaught());
   25064             : 
   25065           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25066           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25067             : 
   25068             :   EnableDebugger(isolate);
   25069             : 
   25070             :   v8::Local<Script> script =
   25071             :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25072           5 :                                   origin)
   25073           5 :           .ToLocalChecked();
   25074             : 
   25075             :   Maybe<uint32_t> result =
   25076          10 :       script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
   25077           5 :   CHECK_EQ(3U, result.FromMaybe(0));
   25078             : 
   25079           5 :   delete[] full_source;
   25080             : 
   25081           5 :   DisableDebugger(isolate);
   25082           5 : }
   25083             : 
   25084             : 
   25085       25880 : TEST(StreamingScriptWithInvalidUtf8) {
   25086             :   // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
   25087             :   // chunk don't produce a crash.
   25088             :   const char* reference = "\xec\x92\x81\x80\x80";
   25089             :   char chunk1[] =
   25090             :       "function foo() {\n"
   25091             :       "  // This function will contain an UTF-8 character which is not in\n"
   25092             :       "  // ASCII.\n"
   25093           5 :       "  var foobXXXXX";  // Too many bytes which look like incomplete chars!
   25094             :   char chunk2[] =
   25095             :       "r = 13;\n"
   25096             :       "  return foob\xec\x92\x81\x80\x80r;\n"
   25097           5 :       "}\n";
   25098           5 :   for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
   25099             : 
   25100           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25101           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
   25102           5 : }
   25103             : 
   25104             : 
   25105       25880 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
   25106             :   // Regression test: Stream data where there are several multi-byte UTF-8
   25107             :   // characters in a sequence and one of them is split between two data chunks.
   25108             :   const char* reference = "\xec\x92\x81";
   25109             :   char chunk1[] =
   25110             :       "function foo() {\n"
   25111             :       "  // This function will contain an UTF-8 character which is not in\n"
   25112             :       "  // ASCII.\n"
   25113           5 :       "  var foob\xec\x92\x81X";
   25114             :   char chunk2[] =
   25115             :       "XXr = 13;\n"
   25116             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25117           5 :       "}\n";
   25118           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25119           5 :   chunk2[0] = reference[1];
   25120           5 :   chunk2[1] = reference[2];
   25121           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25122           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25123           5 : }
   25124             : 
   25125             : 
   25126       25880 : TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
   25127             :   // Another regression test, similar to the previous one. The difference is
   25128             :   // that the split character is not the last one in the sequence.
   25129             :   const char* reference = "\xec\x92\x81";
   25130             :   char chunk1[] =
   25131             :       "function foo() {\n"
   25132             :       "  // This function will contain an UTF-8 character which is not in\n"
   25133             :       "  // ASCII.\n"
   25134           5 :       "  var foobX";
   25135             :   char chunk2[] =
   25136             :       "XX\xec\x92\x81r = 13;\n"
   25137             :       "  return foob\xec\x92\x81\xec\x92\x81r;\n"
   25138           5 :       "}\n";
   25139           5 :   chunk1[strlen(chunk1) - 1] = reference[0];
   25140           5 :   chunk2[0] = reference[1];
   25141           5 :   chunk2[1] = reference[2];
   25142           5 :   const char* chunks[] = {chunk1, chunk2, "foo();", nullptr};
   25143           5 :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
   25144           5 : }
   25145             : 
   25146             : 
   25147       25880 : TEST(StreamingWithHarmonyScopes) {
   25148             :   // Don't use RunStreamingTest here so that both scripts get to use the same
   25149             :   // LocalContext and HandleScope.
   25150           5 :   LocalContext env;
   25151           5 :   v8::Isolate* isolate = env->GetIsolate();
   25152          10 :   v8::HandleScope scope(isolate);
   25153             : 
   25154             :   // First, run a script with a let variable.
   25155             :   CompileRun("\"use strict\"; let x = 1;");
   25156             : 
   25157             :   // Then stream a script which (erroneously) tries to introduce the same
   25158             :   // variable again.
   25159           5 :   const char* chunks[] = {"\"use strict\"; let x = 2;", nullptr};
   25160             : 
   25161          10 :   v8::TryCatch try_catch(isolate);
   25162             :   v8::ScriptCompiler::StreamedSource source(
   25163             :       new TestSourceStream(chunks),
   25164          15 :       v8::ScriptCompiler::StreamedSource::ONE_BYTE);
   25165             :   v8::ScriptCompiler::ScriptStreamingTask* task =
   25166           5 :       v8::ScriptCompiler::StartStreamingScript(isolate, &source);
   25167           5 :   task->Run();
   25168           5 :   delete task;
   25169             : 
   25170             :   // Parsing should succeed (the script will be parsed and compiled in a context
   25171             :   // independent way, so the error is not detected).
   25172           5 :   CHECK(!try_catch.HasCaught());
   25173             : 
   25174           5 :   v8::ScriptOrigin origin(v8_str("http://foo.com"));
   25175           5 :   char* full_source = TestSourceStream::FullSourceString(chunks);
   25176             :   v8::Local<Script> script =
   25177             :       v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
   25178           5 :                                   origin)
   25179           5 :           .ToLocalChecked();
   25180           5 :   CHECK(!script.IsEmpty());
   25181           5 :   CHECK(!try_catch.HasCaught());
   25182             : 
   25183             :   // Running the script exposes the error.
   25184          10 :   CHECK(script->Run(env.local()).IsEmpty());
   25185           5 :   CHECK(try_catch.HasCaught());
   25186          10 :   delete[] full_source;
   25187           5 : }
   25188             : 
   25189             : 
   25190       25880 : TEST(CodeCache) {
   25191             :   v8::Isolate::CreateParams create_params;
   25192           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25193             : 
   25194             :   const char* source = "Math.sqrt(4)";
   25195             :   const char* origin = "code cache test";
   25196             :   v8::ScriptCompiler::CachedData* cache;
   25197             : 
   25198           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   25199             :   {
   25200             :     v8::Isolate::Scope iscope(isolate1);
   25201          10 :     v8::HandleScope scope(isolate1);
   25202           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   25203             :     v8::Context::Scope cscope(context);
   25204           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25205           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25206             :     v8::ScriptCompiler::Source source(source_string, script_origin);
   25207             :     v8::ScriptCompiler::CompileOptions option =
   25208             :         v8::ScriptCompiler::kNoCompileOptions;
   25209             :     v8::Local<v8::Script> script =
   25210           5 :         v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25211           5 :     cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
   25212             :   }
   25213           5 :   isolate1->Dispose();
   25214             : 
   25215           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   25216             :   {
   25217             :     v8::Isolate::Scope iscope(isolate2);
   25218          10 :     v8::HandleScope scope(isolate2);
   25219           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   25220             :     v8::Context::Scope cscope(context);
   25221           5 :     v8::Local<v8::String> source_string = v8_str(source);
   25222           5 :     v8::ScriptOrigin script_origin(v8_str(origin));
   25223             :     v8::ScriptCompiler::Source source(source_string, script_origin, cache);
   25224             :     v8::ScriptCompiler::CompileOptions option =
   25225             :         v8::ScriptCompiler::kConsumeCodeCache;
   25226             :     v8::Local<v8::Script> script;
   25227             :     {
   25228             :       i::DisallowCompilation no_compile(
   25229             :           reinterpret_cast<i::Isolate*>(isolate2));
   25230             :       script = v8::ScriptCompiler::Compile(context, &source, option)
   25231           5 :                    .ToLocalChecked();
   25232             :     }
   25233          20 :     CHECK_EQ(2, script->Run(context)
   25234             :                     .ToLocalChecked()
   25235             :                     ->ToInt32(context)
   25236             :                     .ToLocalChecked()
   25237             :                     ->Int32Value(context)
   25238             :                     .FromJust());
   25239             :   }
   25240           5 :   isolate2->Dispose();
   25241           5 : }
   25242             : 
   25243           0 : v8::MaybeLocal<Module> UnexpectedModuleResolveCallback(Local<Context> context,
   25244             :                                                        Local<String> specifier,
   25245             :                                                        Local<Module> referrer) {
   25246           0 :   CHECK_WITH_MSG(false, "Unexpected call to resolve callback");
   25247             : }
   25248             : 
   25249             : namespace {
   25250             : 
   25251          10 : Local<Module> CompileAndInstantiateModule(v8::Isolate* isolate,
   25252             :                                           Local<Context> context,
   25253             :                                           const char* resource_name,
   25254             :                                           const char* source) {
   25255          10 :   Local<String> source_string = v8_str(source);
   25256             :   v8::ScriptOrigin script_origin(
   25257             :       v8_str(resource_name), Local<v8::Integer>(), Local<v8::Integer>(),
   25258             :       Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   25259          10 :       Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   25260             :   v8::ScriptCompiler::Source script_compiler_source(source_string,
   25261             :                                                     script_origin);
   25262             :   Local<Module> module =
   25263             :       v8::ScriptCompiler::CompileModule(isolate, &script_compiler_source)
   25264          10 :           .ToLocalChecked();
   25265             :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25266          20 :       .ToChecked();
   25267             : 
   25268          20 :   return module;
   25269             : }
   25270             : 
   25271           5 : Local<Module> CompileAndInstantiateModuleFromCache(
   25272             :     v8::Isolate* isolate, Local<Context> context, const char* resource_name,
   25273             :     const char* source, v8::ScriptCompiler::CachedData* cache) {
   25274           5 :   Local<String> source_string = v8_str(source);
   25275             :   v8::ScriptOrigin script_origin(
   25276             :       v8_str(resource_name), Local<v8::Integer>(), Local<v8::Integer>(),
   25277             :       Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   25278           5 :       Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   25279             :   v8::ScriptCompiler::Source script_compiler_source(source_string,
   25280             :                                                     script_origin, cache);
   25281             : 
   25282             :   Local<Module> module =
   25283             :       v8::ScriptCompiler::CompileModule(isolate, &script_compiler_source,
   25284             :                                         v8::ScriptCompiler::kConsumeCodeCache)
   25285           5 :           .ToLocalChecked();
   25286             :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25287          10 :       .ToChecked();
   25288             : 
   25289          10 :   return module;
   25290             : }
   25291             : 
   25292             : }  // namespace
   25293             : 
   25294       25880 : TEST(ModuleCodeCache) {
   25295             :   v8::Isolate::CreateParams create_params;
   25296           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25297             : 
   25298             :   const char* origin = "code cache test";
   25299             :   const char* source =
   25300             :       "export default 5; export const a = 10; function f() { return 42; } "
   25301             :       "(function() { return f(); })();";
   25302             : 
   25303             :   v8::ScriptCompiler::CachedData* cache;
   25304             :   {
   25305           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25306             :     {
   25307             :       v8::Isolate::Scope iscope(isolate);
   25308          10 :       v8::HandleScope scope(isolate);
   25309           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25310             :       v8::Context::Scope cscope(context);
   25311             : 
   25312             :       Local<Module> module =
   25313           5 :           CompileAndInstantiateModule(isolate, context, origin, source);
   25314             : 
   25315             :       // Fetch the shared function info before evaluation.
   25316             :       Local<v8::UnboundModuleScript> unbound_module_script =
   25317           5 :           module->GetUnboundModuleScript();
   25318             : 
   25319             :       // Evaluate for possible lazy compilation.
   25320             :       Local<Value> completion_value =
   25321           5 :           module->Evaluate(context).ToLocalChecked();
   25322          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25323             : 
   25324             :       // Now create the cache. Note that it is freed, obscurely, when
   25325             :       // ScriptCompiler::Source goes out of scope below.
   25326           5 :       cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
   25327             :     }
   25328           5 :     isolate->Dispose();
   25329             :   }
   25330             : 
   25331             :   // Test that the cache is consumed and execution still works.
   25332             :   {
   25333             :     // Disable --always_opt, otherwise we try to optimize during module
   25334             :     // instantiation, violating the DisallowCompilation scope.
   25335           5 :     i::FLAG_always_opt = false;
   25336           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25337             :     {
   25338             :       v8::Isolate::Scope iscope(isolate);
   25339          10 :       v8::HandleScope scope(isolate);
   25340           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25341             :       v8::Context::Scope cscope(context);
   25342             : 
   25343             :       Local<Module> module;
   25344             :       {
   25345             :         i::DisallowCompilation no_compile(
   25346             :             reinterpret_cast<i::Isolate*>(isolate));
   25347             :         module = CompileAndInstantiateModuleFromCache(isolate, context, origin,
   25348           5 :                                                       source, cache);
   25349             :       }
   25350             : 
   25351             :       Local<Value> completion_value =
   25352           5 :           module->Evaluate(context).ToLocalChecked();
   25353          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25354             :     }
   25355           5 :     isolate->Dispose();
   25356             :   }
   25357           5 : }
   25358             : 
   25359             : // Tests that the code cache does not confuse the same source code compiled as a
   25360             : // script and as a module.
   25361       25880 : TEST(CodeCacheModuleScriptMismatch) {
   25362             :   v8::Isolate::CreateParams create_params;
   25363           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25364             : 
   25365             :   const char* origin = "code cache test";
   25366             :   const char* source = "42";
   25367             : 
   25368             :   v8::ScriptCompiler::CachedData* cache;
   25369             :   {
   25370           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25371             :     {
   25372             :       v8::Isolate::Scope iscope(isolate);
   25373          10 :       v8::HandleScope scope(isolate);
   25374           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25375             :       v8::Context::Scope cscope(context);
   25376             : 
   25377             :       Local<Module> module =
   25378           5 :           CompileAndInstantiateModule(isolate, context, origin, source);
   25379             : 
   25380             :       // Fetch the shared function info before evaluation.
   25381             :       Local<v8::UnboundModuleScript> unbound_module_script =
   25382           5 :           module->GetUnboundModuleScript();
   25383             : 
   25384             :       // Evaluate for possible lazy compilation.
   25385             :       Local<Value> completion_value =
   25386           5 :           module->Evaluate(context).ToLocalChecked();
   25387          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25388             : 
   25389             :       // Now create the cache. Note that it is freed, obscurely, when
   25390             :       // ScriptCompiler::Source goes out of scope below.
   25391           5 :       cache = v8::ScriptCompiler::CreateCodeCache(unbound_module_script);
   25392             :     }
   25393           5 :     isolate->Dispose();
   25394             :   }
   25395             : 
   25396             :   // Test that the cache is not consumed when source is compiled as a script.
   25397             :   {
   25398           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25399             :     {
   25400             :       v8::Isolate::Scope iscope(isolate);
   25401          10 :       v8::HandleScope scope(isolate);
   25402           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25403             :       v8::Context::Scope cscope(context);
   25404             : 
   25405           5 :       v8::ScriptOrigin script_origin(v8_str(origin));
   25406             :       v8::ScriptCompiler::Source script_compiler_source(v8_str(source),
   25407           5 :                                                         script_origin, cache);
   25408             : 
   25409             :       v8::Local<v8::Script> script =
   25410             :           v8::ScriptCompiler::Compile(context, &script_compiler_source,
   25411             :                                       v8::ScriptCompiler::kConsumeCodeCache)
   25412           5 :               .ToLocalChecked();
   25413             : 
   25414           5 :       CHECK(cache->rejected);
   25415             : 
   25416          20 :       CHECK_EQ(42, script->Run(context)
   25417             :                        .ToLocalChecked()
   25418             :                        ->ToInt32(context)
   25419             :                        .ToLocalChecked()
   25420             :                        ->Int32Value(context)
   25421             :                        .FromJust());
   25422             :     }
   25423           5 :     isolate->Dispose();
   25424             :   }
   25425           5 : }
   25426             : 
   25427             : // Same as above but other way around.
   25428       25880 : TEST(CodeCacheScriptModuleMismatch) {
   25429             :   v8::Isolate::CreateParams create_params;
   25430           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   25431             : 
   25432             :   const char* origin = "code cache test";
   25433             :   const char* source = "42";
   25434             : 
   25435             :   v8::ScriptCompiler::CachedData* cache;
   25436             :   {
   25437           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25438             :     {
   25439             :       v8::Isolate::Scope iscope(isolate);
   25440          10 :       v8::HandleScope scope(isolate);
   25441           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25442             :       v8::Context::Scope cscope(context);
   25443           5 :       v8::Local<v8::String> source_string = v8_str(source);
   25444           5 :       v8::ScriptOrigin script_origin(v8_str(origin));
   25445             :       v8::ScriptCompiler::Source source(source_string, script_origin);
   25446             :       v8::ScriptCompiler::CompileOptions option =
   25447             :           v8::ScriptCompiler::kNoCompileOptions;
   25448             :       v8::Local<v8::Script> script =
   25449             :           v8::ScriptCompiler::Compile(context, &source, option)
   25450           5 :               .ToLocalChecked();
   25451           5 :       cache = v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript());
   25452             :     }
   25453           5 :     isolate->Dispose();
   25454             :   }
   25455             : 
   25456             :   // Test that the cache is not consumed when source is compiled as a module.
   25457             :   {
   25458           5 :     v8::Isolate* isolate = v8::Isolate::New(create_params);
   25459             :     {
   25460             :       v8::Isolate::Scope iscope(isolate);
   25461          10 :       v8::HandleScope scope(isolate);
   25462           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
   25463             :       v8::Context::Scope cscope(context);
   25464             : 
   25465             :       v8::ScriptOrigin script_origin(
   25466             :           v8_str(origin), Local<v8::Integer>(), Local<v8::Integer>(),
   25467             :           Local<v8::Boolean>(), Local<v8::Integer>(), Local<v8::Value>(),
   25468           5 :           Local<v8::Boolean>(), Local<v8::Boolean>(), True(isolate));
   25469             :       v8::ScriptCompiler::Source script_compiler_source(v8_str(source),
   25470           5 :                                                         script_origin, cache);
   25471             : 
   25472             :       Local<Module> module = v8::ScriptCompiler::CompileModule(
   25473             :                                  isolate, &script_compiler_source,
   25474             :                                  v8::ScriptCompiler::kConsumeCodeCache)
   25475           5 :                                  .ToLocalChecked();
   25476             :       module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25477          10 :           .ToChecked();
   25478             : 
   25479           5 :       CHECK(cache->rejected);
   25480             : 
   25481             :       Local<Value> completion_value =
   25482           5 :           module->Evaluate(context).ToLocalChecked();
   25483          10 :       CHECK_EQ(42, completion_value->Int32Value(context).FromJust());
   25484             :     }
   25485           5 :     isolate->Dispose();
   25486             :   }
   25487           5 : }
   25488             : 
   25489             : // Tests that compilation can handle a garbled cache.
   25490       25880 : TEST(InvalidCodeCacheDataInCompileModule) {
   25491           5 :   v8::V8::Initialize();
   25492           5 :   v8::Isolate* isolate = CcTest::isolate();
   25493           5 :   v8::HandleScope scope(isolate);
   25494          10 :   LocalContext local_context;
   25495             : 
   25496             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   25497             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   25498           5 :   Local<String> origin = v8_str("origin");
   25499             :   int length = 16;
   25500             :   v8::ScriptCompiler::CachedData* cached_data =
   25501           5 :       new v8::ScriptCompiler::CachedData(data, length);
   25502           5 :   CHECK(!cached_data->rejected);
   25503             : 
   25504             :   v8::ScriptOrigin script_origin(
   25505             :       origin, Local<v8::Integer>(), Local<v8::Integer>(), Local<v8::Boolean>(),
   25506             :       Local<v8::Integer>(), Local<v8::Value>(), Local<v8::Boolean>(),
   25507             :       Local<v8::Boolean>(), True(isolate));
   25508           5 :   v8::ScriptCompiler::Source source(v8_str("42"), script_origin, cached_data);
   25509           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   25510             : 
   25511             :   Local<Module> module =
   25512             :       v8::ScriptCompiler::CompileModule(isolate, &source,
   25513             :                                         v8::ScriptCompiler::kConsumeCodeCache)
   25514           5 :           .ToLocalChecked();
   25515             :   module->InstantiateModule(context, UnexpectedModuleResolveCallback)
   25516          10 :       .ToChecked();
   25517             : 
   25518           5 :   CHECK(cached_data->rejected);
   25519          15 :   CHECK_EQ(42, module->Evaluate(context)
   25520             :                    .ToLocalChecked()
   25521             :                    ->Int32Value(context)
   25522           5 :                    .FromJust());
   25523           5 : }
   25524             : 
   25525           5 : void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
   25526             :   const char* garbage = "garbage garbage garbage garbage garbage garbage";
   25527             :   const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
   25528             :   int length = 16;
   25529             :   v8::ScriptCompiler::CachedData* cached_data =
   25530           5 :       new v8::ScriptCompiler::CachedData(data, length);
   25531           5 :   CHECK(!cached_data->rejected);
   25532           5 :   v8::ScriptOrigin origin(v8_str("origin"));
   25533           5 :   v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
   25534           5 :   v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
   25535             :   v8::Local<v8::Script> script =
   25536           5 :       v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
   25537           5 :   CHECK(cached_data->rejected);
   25538          15 :   CHECK_EQ(
   25539             :       42,
   25540             :       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
   25541           5 : }
   25542             : 
   25543             : 
   25544       25880 : TEST(InvalidCodeCacheData) {
   25545           5 :   v8::V8::Initialize();
   25546           5 :   v8::HandleScope scope(CcTest::isolate());
   25547          10 :   LocalContext context;
   25548          10 :   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
   25549           5 : }
   25550             : 
   25551             : 
   25552       25880 : TEST(StringConcatOverflow) {
   25553           5 :   v8::V8::Initialize();
   25554           5 :   v8::Isolate* isolate = CcTest::isolate();
   25555           5 :   v8::HandleScope scope(isolate);
   25556             :   RandomLengthOneByteResource* r =
   25557           5 :       new RandomLengthOneByteResource(i::String::kMaxLength);
   25558             :   v8::Local<v8::String> str =
   25559           5 :       v8::String::NewExternalOneByte(isolate, r).ToLocalChecked();
   25560           5 :   CHECK(!str.IsEmpty());
   25561          10 :   v8::TryCatch try_catch(isolate);
   25562           5 :   v8::Local<v8::String> result = v8::String::Concat(isolate, str, str);
   25563           5 :   v8::String::Concat(CcTest::isolate(), str, str);
   25564           5 :   CHECK(result.IsEmpty());
   25565          10 :   CHECK(!try_catch.HasCaught());
   25566           5 : }
   25567             : 
   25568       25879 : TEST(TurboAsmDisablesDetach) {
   25569             : #ifndef V8_LITE_MODE
   25570           4 :   i::FLAG_opt = true;
   25571           4 :   i::FLAG_allow_natives_syntax = true;
   25572           4 :   v8::V8::Initialize();
   25573           4 :   v8::HandleScope scope(CcTest::isolate());
   25574           8 :   LocalContext context;
   25575             :   const char* load =
   25576             :       "function Module(stdlib, foreign, heap) {"
   25577             :       "  'use asm';"
   25578             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   25579             :       "  function load() { return MEM32[0] | 0; }"
   25580             :       "  return { load: load };"
   25581             :       "}"
   25582             :       "var buffer = new ArrayBuffer(4096);"
   25583             :       "var module = Module(this, {}, buffer);"
   25584             :       "%OptimizeFunctionOnNextCall(module.load);"
   25585             :       "module.load();"
   25586             :       "buffer";
   25587             : 
   25588             :   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   25589           4 :   CHECK(!result->IsDetachable());
   25590             : 
   25591             :   const char* store =
   25592             :       "function Module(stdlib, foreign, heap) {"
   25593             :       "  'use asm';"
   25594             :       "  var MEM32 = new stdlib.Int32Array(heap);"
   25595             :       "  function store() { MEM32[0] = 0; }"
   25596             :       "  return { store: store };"
   25597             :       "}"
   25598             :       "var buffer = new ArrayBuffer(4096);"
   25599             :       "var module = Module(this, {}, buffer);"
   25600             :       "%OptimizeFunctionOnNextCall(module.store);"
   25601             :       "module.store();"
   25602             :       "buffer";
   25603             : 
   25604             :   result = CompileRun(store).As<v8::ArrayBuffer>();
   25605           8 :   CHECK(!result->IsDetachable());
   25606             : #endif  // V8_LITE_MODE
   25607           4 : }
   25608             : 
   25609       25880 : TEST(ClassPrototypeCreationContext) {
   25610           5 :   v8::Isolate* isolate = CcTest::isolate();
   25611           5 :   v8::HandleScope handle_scope(isolate);
   25612          10 :   LocalContext env;
   25613             : 
   25614             :   Local<Object> result = Local<Object>::Cast(
   25615             :       CompileRun("'use strict'; class Example { }; Example.prototype"));
   25616          15 :   CHECK(env.local() == result->CreationContext());
   25617           5 : }
   25618             : 
   25619             : 
   25620       25880 : TEST(SimpleStreamingScriptWithSourceURL) {
   25621             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
   25622           5 :                           "//# sourceURL=bar2.js\n", nullptr};
   25623             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25624           5 :                    "bar2.js");
   25625           5 : }
   25626             : 
   25627             : 
   25628       25880 : TEST(StreamingScriptWithSplitSourceURL) {
   25629             :   const char* chunks[] = {"function foo() { ret", "urn 13; } f",
   25630           5 :                           "oo();\n//# sourceURL=b", "ar2.js\n", nullptr};
   25631             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25632           5 :                    "bar2.js");
   25633           5 : }
   25634             : 
   25635             : 
   25636       25880 : TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
   25637             :   const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
   25638           5 :                           " sourceMappingURL=bar2.js\n", "foo();", nullptr};
   25639             :   RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
   25640           5 :                    nullptr, "bar2.js");
   25641           5 : }
   25642             : 
   25643             : 
   25644       25880 : TEST(NewStringRangeError) {
   25645             :   // This test uses a lot of memory and fails with flaky OOM when run
   25646             :   // with --stress-incremental-marking on TSAN.
   25647           5 :   i::FLAG_stress_incremental_marking = false;
   25648           5 :   v8::Isolate* isolate = CcTest::isolate();
   25649           5 :   v8::HandleScope handle_scope(isolate);
   25650             :   const int length = i::String::kMaxLength + 1;
   25651             :   const int buffer_size = length * sizeof(uint16_t);
   25652           5 :   void* buffer = malloc(buffer_size);
   25653           5 :   if (buffer == nullptr) return;
   25654             :   memset(buffer, 'A', buffer_size);
   25655             :   {
   25656           5 :     v8::TryCatch try_catch(isolate);
   25657             :     char* data = reinterpret_cast<char*>(buffer);
   25658          10 :     CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
   25659             :                                   length)
   25660             :               .IsEmpty());
   25661           5 :     CHECK(!try_catch.HasCaught());
   25662             :   }
   25663             :   {
   25664           5 :     v8::TryCatch try_catch(isolate);
   25665             :     uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
   25666          10 :     CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
   25667             :                                      length)
   25668             :               .IsEmpty());
   25669           5 :     CHECK(!try_catch.HasCaught());
   25670             :   }
   25671             :   {
   25672           5 :     v8::TryCatch try_catch(isolate);
   25673             :     uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
   25674          10 :     CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
   25675             :                                      length)
   25676             :               .IsEmpty());
   25677           5 :     CHECK(!try_catch.HasCaught());
   25678             :   }
   25679           5 :   free(buffer);
   25680             : }
   25681             : 
   25682             : 
   25683       25875 : TEST(SealHandleScope) {
   25684           0 :   v8::Isolate* isolate = CcTest::isolate();
   25685           0 :   v8::HandleScope handle_scope(isolate);
   25686           0 :   LocalContext env;
   25687             : 
   25688           0 :   v8::SealHandleScope seal(isolate);
   25689             : 
   25690             :   // Should fail
   25691           0 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25692             : 
   25693           0 :   USE(obj);
   25694           0 : }
   25695             : 
   25696             : 
   25697       25880 : TEST(SealHandleScopeNested) {
   25698           5 :   v8::Isolate* isolate = CcTest::isolate();
   25699           5 :   v8::HandleScope handle_scope(isolate);
   25700          10 :   LocalContext env;
   25701             : 
   25702          10 :   v8::SealHandleScope seal(isolate);
   25703             : 
   25704             :   {
   25705           5 :     v8::HandleScope handle_scope(isolate);
   25706             : 
   25707             :     // Should work
   25708           5 :     v8::Local<v8::Object> obj = v8::Object::New(isolate);
   25709             : 
   25710           5 :     USE(obj);
   25711           5 :   }
   25712           5 : }
   25713             : 
   25714             : 
   25715           5 : static void ExtrasBindingTestRuntimeFunction(
   25716          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   25717          15 :   CHECK_EQ(
   25718             :       3,
   25719             :       args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
   25720           5 :   args.GetReturnValue().Set(v8_num(7));
   25721           5 : }
   25722             : 
   25723       25880 : TEST(ExtrasFunctionSource) {
   25724           5 :   v8::Isolate* isolate = CcTest::isolate();
   25725           5 :   v8::HandleScope handle_scope(isolate);
   25726          10 :   LocalContext env;
   25727             : 
   25728           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25729             : 
   25730             :   // Functions defined in extras do not expose source code.
   25731          15 :   auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
   25732           5 :                   .ToLocalChecked()
   25733             :                   .As<v8::Function>();
   25734             :   auto undefined = v8::Undefined(isolate);
   25735          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25736           5 :                     .ToLocalChecked()
   25737             :                     .As<v8::String>();
   25738          10 :   CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
   25739             : 
   25740             :   // Functions defined in extras do not show up in the stack trace.
   25741          15 :   auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
   25742           5 :                      .ToLocalChecked()
   25743             :                      .As<v8::Function>();
   25744          25 :   CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
   25745             :   ExpectString(
   25746             :       "function f(x) { return wrapper(x) }"
   25747             :       "function g() { return new Error().stack; }"
   25748             :       "f(g)",
   25749             :       "Error\n"
   25750             :       "    at g (<anonymous>:1:58)\n"
   25751             :       "    at f (<anonymous>:1:24)\n"
   25752          10 :       "    at <anonymous>:1:78");
   25753           5 : }
   25754             : 
   25755       25880 : TEST(ExtrasBindingObject) {
   25756           5 :   v8::Isolate* isolate = CcTest::isolate();
   25757           5 :   v8::HandleScope handle_scope(isolate);
   25758          10 :   LocalContext env;
   25759             : 
   25760             :   // standalone.gypi ensures we include the test-extra.js file, which should
   25761             :   // export the tested functions.
   25762           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25763             : 
   25764          15 :   auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
   25765           5 :                   .ToLocalChecked()
   25766             :                   .As<v8::Function>();
   25767             :   auto undefined = v8::Undefined(isolate);
   25768          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25769           5 :                     .ToLocalChecked()
   25770             :                     .As<v8::Number>();
   25771          10 :   CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
   25772             : 
   25773             :   v8::Local<v8::FunctionTemplate> runtimeFunction =
   25774           5 :       v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
   25775             :   binding->Set(env.local(), v8_str("runtime"),
   25776          25 :                runtimeFunction->GetFunction(env.local()).ToLocalChecked())
   25777          10 :       .FromJust();
   25778          15 :   func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
   25779           5 :              .ToLocalChecked()
   25780             :              .As<v8::Function>();
   25781          10 :   result = func->Call(env.local(), undefined, 0, {})
   25782           5 :                .ToLocalChecked()
   25783             :                .As<v8::Number>();
   25784          15 :   CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
   25785           5 : }
   25786             : 
   25787             : 
   25788       25880 : TEST(ExtrasCreatePromise) {
   25789           5 :   i::FLAG_allow_natives_syntax = true;
   25790           5 :   LocalContext context;
   25791           5 :   v8::Isolate* isolate = context->GetIsolate();
   25792          10 :   v8::HandleScope handle_scope(isolate);
   25793             : 
   25794          10 :   LocalContext env;
   25795           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25796             : 
   25797          15 :   auto func = binding->Get(env.local(), v8_str("testCreatePromise"))
   25798           5 :                   .ToLocalChecked()
   25799             :                   .As<v8::Function>();
   25800          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25801             : 
   25802             :   auto promise = CompileRun(
   25803             :                      "func();\n"
   25804             :                      "func();\n"
   25805             :                      "%OptimizeFunctionOnNextCall(func);\n"
   25806             :                      "func()\n")
   25807             :                      .As<v8::Promise>();
   25808          10 :   CHECK_EQ(v8::Promise::kPending, promise->State());
   25809           5 : }
   25810             : 
   25811       25880 : TEST(ExtrasCreatePromiseWithParent) {
   25812           5 :   i::FLAG_allow_natives_syntax = true;
   25813           5 :   LocalContext context;
   25814           5 :   v8::Isolate* isolate = context->GetIsolate();
   25815          10 :   v8::HandleScope handle_scope(isolate);
   25816             : 
   25817          10 :   LocalContext env;
   25818           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25819             : 
   25820          15 :   auto func = binding->Get(env.local(), v8_str("testCreatePromiseWithParent"))
   25821           5 :                   .ToLocalChecked()
   25822             :                   .As<v8::Function>();
   25823          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25824             : 
   25825             :   auto promise = CompileRun(
   25826             :                      "var parent = new Promise((a, b) => {});\n"
   25827             :                      "func(parent);\n"
   25828             :                      "func(parent);\n"
   25829             :                      "%OptimizeFunctionOnNextCall(func);\n"
   25830             :                      "func(parent)\n")
   25831             :                      .As<v8::Promise>();
   25832          10 :   CHECK_EQ(v8::Promise::kPending, promise->State());
   25833           5 : }
   25834             : 
   25835       25880 : TEST(ExtrasRejectPromise) {
   25836           5 :   i::FLAG_allow_natives_syntax = true;
   25837           5 :   LocalContext context;
   25838           5 :   v8::Isolate* isolate = context->GetIsolate();
   25839          10 :   v8::HandleScope handle_scope(isolate);
   25840             : 
   25841          10 :   LocalContext env;
   25842           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25843             : 
   25844          15 :   auto func = binding->Get(env.local(), v8_str("testRejectPromise"))
   25845           5 :                   .ToLocalChecked()
   25846             :                   .As<v8::Function>();
   25847          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25848             : 
   25849             :   auto rejected_promise = CompileRun(
   25850             :                               "function newPromise() {\n"
   25851             :                               "  return new Promise((a, b) => {});\n"
   25852             :                               "}\n"
   25853             :                               "func(newPromise(), 1);\n"
   25854             :                               "func(newPromise(), 1);\n"
   25855             :                               "%OptimizeFunctionOnNextCall(func);\n"
   25856             :                               "var promise = newPromise();\n"
   25857             :                               "func(promise, 1);\n"
   25858             :                               "promise;\n")
   25859             :                               .As<v8::Promise>();
   25860           5 :   CHECK_EQ(v8::Promise::kRejected, rejected_promise->State());
   25861          20 :   CHECK_EQ(1, rejected_promise->Result()->Int32Value(env.local()).FromJust());
   25862           5 : }
   25863             : 
   25864       25880 : TEST(ExtrasResolvePromise) {
   25865           5 :   i::FLAG_allow_natives_syntax = true;
   25866           5 :   LocalContext context;
   25867           5 :   v8::Isolate* isolate = context->GetIsolate();
   25868          10 :   v8::HandleScope handle_scope(isolate);
   25869             : 
   25870          10 :   LocalContext env;
   25871           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25872             : 
   25873          15 :   auto func = binding->Get(env.local(), v8_str("testResolvePromise"))
   25874           5 :                   .ToLocalChecked()
   25875             :                   .As<v8::Function>();
   25876          25 :   CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   25877             : 
   25878             :   auto pending_promise = CompileRun(
   25879             :                              "function newPromise() {\n"
   25880             :                              "  return new Promise((a, b) => {});\n"
   25881             :                              "}\n"
   25882             :                              "func(newPromise(), newPromise());\n"
   25883             :                              "func(newPromise(), newPromise());\n"
   25884             :                              "%OptimizeFunctionOnNextCall(func);\n"
   25885             :                              "var promise = newPromise();\n"
   25886             :                              "func(promise, newPromise());\n"
   25887             :                              "promise;\n")
   25888             :                              .As<v8::Promise>();
   25889           5 :   CHECK_EQ(v8::Promise::kPending, pending_promise->State());
   25890             : 
   25891             :   auto fulfilled_promise = CompileRun(
   25892             :                                "function newPromise() {\n"
   25893             :                                "  return new Promise((a, b) => {});\n"
   25894             :                                "}\n"
   25895             :                                "func(newPromise(), 1);\n"
   25896             :                                "func(newPromise(), 1);\n"
   25897             :                                "%OptimizeFunctionOnNextCall(func);\n"
   25898             :                                "var promise = newPromise();\n"
   25899             :                                "func(promise, 1);\n"
   25900             :                                "promise;\n")
   25901             :                                .As<v8::Promise>();
   25902           5 :   CHECK_EQ(v8::Promise::kFulfilled, fulfilled_promise->State());
   25903          20 :   CHECK_EQ(1, fulfilled_promise->Result()->Int32Value(env.local()).FromJust());
   25904           5 : }
   25905             : 
   25906       25880 : TEST(ExtrasUtilsObject) {
   25907           5 :   LocalContext context;
   25908           5 :   v8::Isolate* isolate = context->GetIsolate();
   25909          10 :   v8::HandleScope handle_scope(isolate);
   25910             : 
   25911          10 :   LocalContext env;
   25912           5 :   v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
   25913             : 
   25914          15 :   auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
   25915           5 :                   .ToLocalChecked()
   25916             :                   .As<v8::Function>();
   25917             :   auto undefined = v8::Undefined(isolate);
   25918          10 :   auto result = func->Call(env.local(), undefined, 0, {})
   25919           5 :                     .ToLocalChecked()
   25920             :                     .As<v8::Object>();
   25921             : 
   25922          15 :   auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
   25923           5 :                             .ToLocalChecked()
   25924             :                             .As<v8::Symbol>();
   25925             :   i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
   25926           5 :   CHECK(ips->IsPrivate());
   25927             : 
   25928             :   CompileRun("var result = 0; function store(x) { result = x; }");
   25929           5 :   auto store = CompileRun("store").As<v8::Function>();
   25930             : 
   25931          15 :   auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
   25932           5 :                                .ToLocalChecked()
   25933             :                                .As<v8::Promise>();
   25934           5 :   fulfilled_promise->Then(env.local(), store).ToLocalChecked();
   25935           5 :   isolate->RunMicrotasks();
   25936          15 :   CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
   25937             : 
   25938             :   auto fulfilled_promise_2 =
   25939          15 :       result->Get(env.local(), v8_str("fulfilledPromise2"))
   25940           5 :           .ToLocalChecked()
   25941             :           .As<v8::Promise>();
   25942           5 :   fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
   25943           5 :   isolate->RunMicrotasks();
   25944          15 :   CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
   25945             : 
   25946          15 :   auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
   25947           5 :                               .ToLocalChecked()
   25948             :                               .As<v8::Promise>();
   25949           5 :   rejected_promise->Catch(env.local(), store).ToLocalChecked();
   25950           5 :   isolate->RunMicrotasks();
   25951          15 :   CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
   25952             : 
   25953             :   auto rejected_but_handled_promise =
   25954          15 :       result->Get(env.local(), v8_str("rejectedButHandledPromise"))
   25955           5 :           .ToLocalChecked()
   25956             :           .As<v8::Promise>();
   25957           5 :   CHECK(rejected_but_handled_promise->HasHandler());
   25958             : 
   25959          15 :   auto promise_states = result->Get(env.local(), v8_str("promiseStates"))
   25960           5 :                             .ToLocalChecked()
   25961             :                             .As<v8::String>();
   25962          10 :   String::Utf8Value promise_states_string(isolate, promise_states);
   25963           5 :   CHECK_EQ(0, strcmp(*promise_states_string, "pending fulfilled rejected"));
   25964             : 
   25965          15 :   auto promise_is_promise = result->Get(env.local(), v8_str("promiseIsPromise"))
   25966           5 :                                 .ToLocalChecked()
   25967             :                                 .As<v8::Boolean>();
   25968           5 :   CHECK_EQ(true, promise_is_promise->Value());
   25969             : 
   25970             :   auto thenable_is_promise =
   25971          15 :       result->Get(env.local(), v8_str("thenableIsPromise"))
   25972           5 :           .ToLocalChecked()
   25973             :           .As<v8::Boolean>();
   25974          10 :   CHECK_EQ(false, thenable_is_promise->Value());
   25975             : 
   25976          15 :   auto uncurry_this = result->Get(env.local(), v8_str("uncurryThis"))
   25977           5 :                           .ToLocalChecked()
   25978             :                           .As<v8::Boolean>();
   25979          10 :   CHECK_EQ(true, uncurry_this->Value());
   25980           5 : }
   25981             : 
   25982             : 
   25983       25880 : TEST(Map) {
   25984           5 :   v8::Isolate* isolate = CcTest::isolate();
   25985           5 :   v8::HandleScope handle_scope(isolate);
   25986          10 :   LocalContext env;
   25987             : 
   25988           5 :   v8::Local<v8::Map> map = v8::Map::New(isolate);
   25989           5 :   CHECK(map->IsObject());
   25990           5 :   CHECK(map->IsMap());
   25991          10 :   CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
   25992           5 :   CHECK_EQ(0U, map->Size());
   25993             : 
   25994             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
   25995           5 :   CHECK(val->IsMap());
   25996             :   map = v8::Local<v8::Map>::Cast(val);
   25997           5 :   CHECK_EQ(2U, map->Size());
   25998             : 
   25999           5 :   v8::Local<v8::Array> contents = map->AsArray();
   26000           5 :   CHECK_EQ(4U, contents->Length());
   26001          10 :   CHECK_EQ(
   26002             :       1,
   26003             :       contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26004          10 :   CHECK_EQ(
   26005             :       2,
   26006             :       contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26007          10 :   CHECK_EQ(
   26008             :       3,
   26009             :       contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
   26010          10 :   CHECK_EQ(
   26011             :       4,
   26012             :       contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
   26013             : 
   26014           5 :   CHECK_EQ(2U, map->Size());
   26015             : 
   26016          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26017          15 :   CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26018             : 
   26019          15 :   CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26020          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26021             : 
   26022          20 :   CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
   26023             :                   .ToLocalChecked()
   26024             :                   ->Int32Value(env.local())
   26025             :                   .FromJust());
   26026          20 :   CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
   26027             :                   .ToLocalChecked()
   26028             :                   ->Int32Value(env.local())
   26029             :                   .FromJust());
   26030             : 
   26031          15 :   CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
   26032             :             .ToLocalChecked()
   26033             :             ->IsUndefined());
   26034             : 
   26035          10 :   CHECK(!map->Set(env.local(), map, map).IsEmpty());
   26036           5 :   CHECK_EQ(3U, map->Size());
   26037          10 :   CHECK(map->Has(env.local(), map).FromJust());
   26038             : 
   26039          10 :   CHECK(map->Delete(env.local(), map).FromJust());
   26040           5 :   CHECK_EQ(2U, map->Size());
   26041          10 :   CHECK(!map->Has(env.local(), map).FromJust());
   26042          10 :   CHECK(!map->Delete(env.local(), map).FromJust());
   26043             : 
   26044           5 :   map->Clear();
   26045          10 :   CHECK_EQ(0U, map->Size());
   26046           5 : }
   26047             : 
   26048             : 
   26049       25880 : TEST(Set) {
   26050           5 :   v8::Isolate* isolate = CcTest::isolate();
   26051           5 :   v8::HandleScope handle_scope(isolate);
   26052          10 :   LocalContext env;
   26053             : 
   26054           5 :   v8::Local<v8::Set> set = v8::Set::New(isolate);
   26055           5 :   CHECK(set->IsObject());
   26056           5 :   CHECK(set->IsSet());
   26057          10 :   CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
   26058           5 :   CHECK_EQ(0U, set->Size());
   26059             : 
   26060             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
   26061           5 :   CHECK(val->IsSet());
   26062             :   set = v8::Local<v8::Set>::Cast(val);
   26063           5 :   CHECK_EQ(2U, set->Size());
   26064             : 
   26065           5 :   v8::Local<v8::Array> keys = set->AsArray();
   26066           5 :   CHECK_EQ(2U, keys->Length());
   26067          10 :   CHECK_EQ(1,
   26068             :            keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
   26069          10 :   CHECK_EQ(2,
   26070             :            keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
   26071             : 
   26072           5 :   CHECK_EQ(2U, set->Size());
   26073             : 
   26074          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
   26075          15 :   CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
   26076             : 
   26077          15 :   CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
   26078          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26079             : 
   26080          10 :   CHECK(!set->Add(env.local(), set).IsEmpty());
   26081           5 :   CHECK_EQ(3U, set->Size());
   26082          10 :   CHECK(set->Has(env.local(), set).FromJust());
   26083             : 
   26084          10 :   CHECK(set->Delete(env.local(), set).FromJust());
   26085           5 :   CHECK_EQ(2U, set->Size());
   26086          10 :   CHECK(!set->Has(env.local(), set).FromJust());
   26087          10 :   CHECK(!set->Delete(env.local(), set).FromJust());
   26088             : 
   26089           5 :   set->Clear();
   26090          10 :   CHECK_EQ(0U, set->Size());
   26091           5 : }
   26092             : 
   26093       25880 : TEST(SetDeleteThenAsArray) {
   26094             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26095           5 :   v8::Isolate* isolate = CcTest::isolate();
   26096           5 :   v8::HandleScope handle_scope(isolate);
   26097          10 :   LocalContext env;
   26098             : 
   26099             :   // make a Set
   26100             :   v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
   26101             :   v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
   26102           5 :   CHECK_EQ(3U, set->Size());
   26103             : 
   26104             :   // delete the "middle" element (using AsArray to
   26105             :   // determine which element is the "middle" element)
   26106           5 :   v8::Local<v8::Array> array1 = set->AsArray();
   26107           5 :   CHECK_EQ(3U, array1->Length());
   26108          15 :   CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
   26109             :             .FromJust());
   26110             : 
   26111             :   // make sure there are no undefined values when we convert to an array again.
   26112           5 :   v8::Local<v8::Array> array2 = set->AsArray();
   26113           5 :   uint32_t length = array2->Length();
   26114           5 :   CHECK_EQ(2U, length);
   26115          10 :   for (uint32_t i = 0; i < length; i++) {
   26116          20 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26117           5 :   }
   26118           5 : }
   26119             : 
   26120       25880 : TEST(MapDeleteThenAsArray) {
   26121             :   // https://bugs.chromium.org/p/v8/issues/detail?id=4946
   26122           5 :   v8::Isolate* isolate = CcTest::isolate();
   26123           5 :   v8::HandleScope handle_scope(isolate);
   26124          10 :   LocalContext env;
   26125             : 
   26126             :   // make a Map
   26127             :   v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
   26128             :   v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
   26129           5 :   CHECK_EQ(3U, map->Size());
   26130             : 
   26131             :   // delete the "middle" element (using AsArray to
   26132             :   // determine which element is the "middle" element)
   26133           5 :   v8::Local<v8::Array> array1 = map->AsArray();
   26134           5 :   CHECK_EQ(6U, array1->Length());
   26135             :   // Map::AsArray returns a flat array, so the second key is at index 2.
   26136          10 :   v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
   26137          10 :   CHECK(map->Delete(env.local(), key).FromJust());
   26138             : 
   26139             :   // make sure there are no undefined values when we convert to an array again.
   26140           5 :   v8::Local<v8::Array> array2 = map->AsArray();
   26141           5 :   uint32_t length = array2->Length();
   26142           5 :   CHECK_EQ(4U, length);
   26143          20 :   for (uint32_t i = 0; i < length; i++) {
   26144          40 :     CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
   26145           5 :   }
   26146           5 : }
   26147             : 
   26148       25880 : TEST(CompatibleReceiverCheckOnCachedICHandler) {
   26149           5 :   v8::Isolate* isolate = CcTest::isolate();
   26150           5 :   v8::HandleScope scope(isolate);
   26151           5 :   v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
   26152           5 :   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
   26153             :   auto returns_42 =
   26154           5 :       v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
   26155          15 :   parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
   26156           5 :   v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
   26157           5 :   child->Inherit(parent);
   26158          10 :   LocalContext env;
   26159          30 :   CHECK(env->Global()
   26160             :             ->Set(env.local(), v8_str("Child"),
   26161             :                   child->GetFunction(env.local()).ToLocalChecked())
   26162             :             .FromJust());
   26163             : 
   26164             :   // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
   26165             :   CompileRun(
   26166             :       "var real = new Child();\n"
   26167             :       "for (var i = 0; i < 3; ++i) {\n"
   26168             :       "  real.age;\n"
   26169             :       "}\n");
   26170             : 
   26171             :   // Check that the cached stub is never used.
   26172             :   ExpectInt32(
   26173             :       "var fake = Object.create(Child.prototype);\n"
   26174             :       "var result = 0;\n"
   26175             :       "function test(d) {\n"
   26176             :       "  if (d == 3) return;\n"
   26177             :       "  try {\n"
   26178             :       "    fake.age;\n"
   26179             :       "    result = 1;\n"
   26180             :       "  } catch (e) {\n"
   26181             :       "  }\n"
   26182             :       "  test(d+1);\n"
   26183             :       "}\n"
   26184             :       "test(0);\n"
   26185             :       "result;\n",
   26186          10 :       0);
   26187           5 : }
   26188             : 
   26189       25881 : THREADED_TEST(ReceiverConversionForAccessors) {
   26190           6 :   LocalContext env;
   26191           6 :   v8::Isolate* isolate = CcTest::isolate();
   26192          12 :   v8::HandleScope scope(isolate);
   26193             :   Local<v8::FunctionTemplate> acc =
   26194           6 :       v8::FunctionTemplate::New(isolate, Returns42);
   26195          42 :   CHECK(env->Global()
   26196             :             ->Set(env.local(), v8_str("acc"),
   26197             :                   acc->GetFunction(env.local()).ToLocalChecked())
   26198             :             .FromJust());
   26199             : 
   26200           6 :   Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
   26201          12 :   templ->SetAccessorProperty(v8_str("acc"), acc, acc);
   26202           6 :   Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
   26203             : 
   26204          30 :   CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
   26205           6 :   CHECK(CompileRun("(p.acc == 42)")->BooleanValue(isolate));
   26206           6 :   CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(isolate));
   26207             : 
   26208           6 :   CHECK(!CompileRun("Number.prototype.__proto__ = p;"
   26209             :                     "var a = 1;")
   26210             :              .IsEmpty());
   26211           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26212           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26213             : 
   26214           6 :   CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
   26215             :                     "var a = true;")
   26216             :              .IsEmpty());
   26217           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26218           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26219             : 
   26220           6 :   CHECK(!CompileRun("String.prototype.__proto__ = p;"
   26221             :                     "var a = 'foo';")
   26222             :              .IsEmpty());
   26223           6 :   CHECK(CompileRun("(a.acc == 42)")->BooleanValue(isolate));
   26224           6 :   CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(isolate));
   26225             : 
   26226           6 :   CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(isolate));
   26227           6 :   CHECK(CompileRun("acc.call(true)==42")->BooleanValue(isolate));
   26228           6 :   CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(isolate));
   26229           6 :   CHECK(CompileRun("acc.call(null) == 42")->BooleanValue(isolate));
   26230          12 :   CHECK(CompileRun("acc.call(undefined) == 42")->BooleanValue(isolate));
   26231           6 : }
   26232             : 
   26233           5 : class FutexInterruptionThread : public v8::base::Thread {
   26234             :  public:
   26235             :   explicit FutexInterruptionThread(v8::Isolate* isolate)
   26236           5 :       : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
   26237             : 
   26238           5 :   void Run() override {
   26239             :     // Wait a bit before terminating.
   26240           5 :     v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
   26241           5 :     isolate_->TerminateExecution();
   26242           5 :   }
   26243             : 
   26244             :  private:
   26245             :   v8::Isolate* isolate_;
   26246             : };
   26247             : 
   26248             : 
   26249       25880 : TEST(FutexInterruption) {
   26250           5 :   i::FLAG_harmony_sharedarraybuffer = true;
   26251           5 :   v8::Isolate* isolate = CcTest::isolate();
   26252           5 :   v8::HandleScope scope(isolate);
   26253          10 :   LocalContext env;
   26254             : 
   26255             :   FutexInterruptionThread timeout_thread(isolate);
   26256             : 
   26257          10 :   v8::TryCatch try_catch(CcTest::isolate());
   26258           5 :   timeout_thread.Start();
   26259             : 
   26260             :   CompileRun(
   26261             :       "var ab = new SharedArrayBuffer(4);"
   26262             :       "var i32a = new Int32Array(ab);"
   26263             :       "Atomics.wait(i32a, 0, 0);");
   26264           5 :   CHECK(try_catch.HasTerminated());
   26265          10 :   timeout_thread.Join();
   26266           5 : }
   26267             : 
   26268       25881 : THREADED_TEST(SharedArrayBuffer_AllocationInformation) {
   26269           6 :   i::FLAG_harmony_sharedarraybuffer = true;
   26270           6 :   LocalContext env;
   26271           6 :   v8::Isolate* isolate = env->GetIsolate();
   26272          12 :   v8::HandleScope handle_scope(isolate);
   26273             : 
   26274             :   const size_t ab_size = 1024;
   26275             :   Local<v8::SharedArrayBuffer> ab =
   26276           6 :       v8::SharedArrayBuffer::New(isolate, ab_size);
   26277          12 :   ScopedSharedArrayBufferContents contents(ab->Externalize());
   26278             : 
   26279             :   // Array buffers should have normal allocation mode.
   26280           6 :   CHECK_EQ(contents.AllocationMode(),
   26281             :            v8::ArrayBuffer::Allocator::AllocationMode::kNormal);
   26282             :   // The allocation must contain the buffer (normally they will be equal, but
   26283             :   // this is not required by the contract).
   26284           6 :   CHECK_NOT_NULL(contents.AllocationBase());
   26285             :   const uintptr_t alloc =
   26286           6 :       reinterpret_cast<uintptr_t>(contents.AllocationBase());
   26287           6 :   const uintptr_t data = reinterpret_cast<uintptr_t>(contents.Data());
   26288           6 :   CHECK_LE(alloc, data);
   26289          12 :   CHECK_LE(data + contents.ByteLength(), alloc + contents.AllocationLength());
   26290           6 : }
   26291             : 
   26292             : static int nb_uncaught_exception_callback_calls = 0;
   26293             : 
   26294             : 
   26295           5 : bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
   26296           5 :   ++nb_uncaught_exception_callback_calls;
   26297           5 :   return false;
   26298             : }
   26299             : 
   26300             : 
   26301       25880 : TEST(AbortOnUncaughtExceptionNoAbort) {
   26302           5 :   v8::Isolate* isolate = CcTest::isolate();
   26303           5 :   v8::HandleScope handle_scope(isolate);
   26304             :   v8::Local<v8::ObjectTemplate> global_template =
   26305           5 :       v8::ObjectTemplate::New(isolate);
   26306          10 :   LocalContext env(nullptr, global_template);
   26307             : 
   26308           5 :   i::FLAG_abort_on_uncaught_exception = true;
   26309           5 :   isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
   26310             : 
   26311             :   CompileRun("function boom() { throw new Error(\"boom\") }");
   26312             : 
   26313           5 :   v8::Local<v8::Object> global_object = env->Global();
   26314             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
   26315          20 :       global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
   26316             : 
   26317          10 :   CHECK(foo->Call(env.local(), global_object, 0, nullptr).IsEmpty());
   26318             : 
   26319          10 :   CHECK_EQ(1, nb_uncaught_exception_callback_calls);
   26320           5 : }
   26321             : 
   26322             : 
   26323       25880 : TEST(AccessCheckedIsConcatSpreadable) {
   26324           5 :   v8::Isolate* isolate = CcTest::isolate();
   26325           5 :   HandleScope scope(isolate);
   26326          10 :   LocalContext env;
   26327             : 
   26328             :   // Object with access check
   26329           5 :   Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
   26330           5 :   spreadable_template->SetAccessCheckCallback(AccessBlocker);
   26331             :   spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
   26332          10 :                            v8::Boolean::New(isolate, true));
   26333             :   Local<Object> object =
   26334           5 :       spreadable_template->NewInstance(env.local()).ToLocalChecked();
   26335             : 
   26336           5 :   allowed_access = true;
   26337          25 :   CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
   26338          15 :   object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
   26339          15 :   object->Set(env.local(), 0U, v8_str("a")).FromJust();
   26340          15 :   object->Set(env.local(), 1U, v8_str("b")).FromJust();
   26341             : 
   26342             :   // Access check is allowed, and the object is spread
   26343             :   CompileRun("var result = [].concat(object)");
   26344             :   ExpectTrue("Array.isArray(result)");
   26345           5 :   ExpectString("result[0]", "a");
   26346           5 :   ExpectString("result[1]", "b");
   26347             :   ExpectTrue("result.length === 2");
   26348             :   ExpectTrue("object[Symbol.isConcatSpreadable]");
   26349             : 
   26350             :   // If access check fails, the value of @@isConcatSpreadable is ignored
   26351           5 :   allowed_access = false;
   26352             :   CompileRun("var result = [].concat(object)");
   26353             :   ExpectTrue("Array.isArray(result)");
   26354             :   ExpectTrue("result[0] === object");
   26355             :   ExpectTrue("result.length === 1");
   26356           5 :   ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
   26357           5 : }
   26358             : 
   26359             : 
   26360       25880 : TEST(AccessCheckedToStringTag) {
   26361           5 :   v8::Isolate* isolate = CcTest::isolate();
   26362           5 :   HandleScope scope(isolate);
   26363          10 :   LocalContext env;
   26364             : 
   26365             :   // Object with access check
   26366           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26367           5 :   object_template->SetAccessCheckCallback(AccessBlocker);
   26368             :   Local<Object> object =
   26369           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26370             : 
   26371           5 :   allowed_access = true;
   26372          25 :   env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
   26373          20 :   object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
   26374          10 :       .FromJust();
   26375             : 
   26376             :   // Access check is allowed, and the toStringTag is read
   26377             :   CompileRun("var result = Object.prototype.toString.call(object)");
   26378           5 :   ExpectString("result", "[object hello]");
   26379           5 :   ExpectString("object[Symbol.toStringTag]", "hello");
   26380             : 
   26381             :   // ToString through the API should succeed too.
   26382             :   String::Utf8Value result_allowed(
   26383          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   26384           5 :   CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
   26385             : 
   26386             :   // If access check fails, the value of @@toStringTag is ignored
   26387           5 :   allowed_access = false;
   26388             :   CompileRun("var result = Object.prototype.toString.call(object)");
   26389           5 :   ExpectString("result", "[object Object]");
   26390             :   ExpectTrue("object[Symbol.toStringTag] === undefined");
   26391             : 
   26392             :   // ToString through the API should also fail.
   26393             :   String::Utf8Value result_denied(
   26394          15 :       isolate, object->ObjectProtoToString(env.local()).ToLocalChecked());
   26395          10 :   CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
   26396           5 : }
   26397             : 
   26398       25880 : TEST(TemplateIteratorPrototypeIntrinsics) {
   26399           5 :   v8::Isolate* isolate = CcTest::isolate();
   26400           5 :   v8::HandleScope scope(isolate);
   26401          10 :   LocalContext env;
   26402             : 
   26403             :   // Object templates.
   26404             :   {
   26405           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26406             :     object_template->SetIntrinsicDataProperty(v8_str("iter_proto"),
   26407          10 :                                               v8::kIteratorPrototype);
   26408             :     Local<Object> object =
   26409           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   26410          25 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   26411             :     ExpectTrue("obj.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   26412             :   }
   26413             :   // Setting %IteratorProto% on the function object's prototype template.
   26414             :   {
   26415           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26416          10 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   26417          15 :         v8_str("iter_proto"), v8::kIteratorPrototype);
   26418             :     Local<Function> func1 =
   26419           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26420          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   26421             :     Local<Function> func2 =
   26422           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26423          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   26424             :     ExpectTrue(
   26425             :         "func1.prototype.iter_proto === "
   26426             :         "[][Symbol.iterator]().__proto__.__proto__");
   26427             :     ExpectTrue(
   26428             :         "func2.prototype.iter_proto === "
   26429             :         "[][Symbol.iterator]().__proto__.__proto__");
   26430             :     ExpectTrue("func1.prototype.iter_proto === func2.prototype.iter_proto");
   26431             : 
   26432           5 :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   26433          25 :     CHECK(env->Global()
   26434             :               ->Set(env.local(), v8_str("instance1"), instance1)
   26435             :               .FromJust());
   26436             :     ExpectFalse("instance1.hasOwnProperty('iter_proto')");
   26437             :     ExpectTrue("'iter_proto' in instance1.__proto__");
   26438             :     ExpectTrue(
   26439             :         "instance1.iter_proto === [][Symbol.iterator]().__proto__.__proto__");
   26440             :   }
   26441             :   // Put %IteratorProto% in a function object's inheritance chain.
   26442             :   {
   26443             :     Local<FunctionTemplate> parent_template =
   26444           5 :         v8::FunctionTemplate::New(isolate);
   26445           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   26446             :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   26447          10 :                                               v8::kIteratorPrototype);
   26448           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26449           5 :     func_template->Inherit(parent_template);
   26450             : 
   26451             :     Local<Function> func =
   26452           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26453          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26454             :     ExpectTrue(
   26455             :         "func.prototype.__proto__ === "
   26456             :         "[][Symbol.iterator]().__proto__.__proto__");
   26457             : 
   26458             :     Local<Object> func_instance =
   26459           5 :         func->NewInstance(env.local()).ToLocalChecked();
   26460          25 :     CHECK(env->Global()
   26461             :               ->Set(env.local(), v8_str("instance"), func_instance)
   26462             :               .FromJust());
   26463             :     ExpectTrue(
   26464             :         "instance.__proto__.__proto__ === "
   26465             :         "[][Symbol.iterator]().__proto__.__proto__");
   26466             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   26467           5 :   }
   26468           5 : }
   26469             : 
   26470       25880 : TEST(TemplateErrorPrototypeIntrinsics) {
   26471           5 :   v8::Isolate* isolate = CcTest::isolate();
   26472           5 :   v8::HandleScope scope(isolate);
   26473          10 :   LocalContext env;
   26474             : 
   26475             :   // Object templates.
   26476             :   {
   26477           5 :     Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26478             :     object_template->SetIntrinsicDataProperty(v8_str("error_proto"),
   26479          10 :                                               v8::kErrorPrototype);
   26480             :     Local<Object> object =
   26481           5 :         object_template->NewInstance(env.local()).ToLocalChecked();
   26482          25 :     CHECK(env->Global()->Set(env.local(), v8_str("obj"), object).FromJust());
   26483             :     ExpectTrue("obj.error_proto === Error.prototype");
   26484           5 :     Local<Value> error = v8::Exception::Error(v8_str("error message"));
   26485          25 :     CHECK(env->Global()->Set(env.local(), v8_str("err"), error).FromJust());
   26486             :     ExpectTrue("obj.error_proto === Object.getPrototypeOf(err)");
   26487             :   }
   26488             :   // Setting %ErrorPrototype% on the function object's prototype template.
   26489             :   {
   26490           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26491          10 :     func_template->PrototypeTemplate()->SetIntrinsicDataProperty(
   26492          15 :         v8_str("error_proto"), v8::kErrorPrototype);
   26493             :     Local<Function> func1 =
   26494           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26495          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func1"), func1).FromJust());
   26496             :     Local<Function> func2 =
   26497           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26498          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
   26499             :     ExpectTrue("func1.prototype.error_proto === Error.prototype");
   26500             :     ExpectTrue("func2.prototype.error_proto === Error.prototype");
   26501             :     ExpectTrue("func1.prototype.error_proto === func2.prototype.error_proto");
   26502             : 
   26503           5 :     Local<Object> instance1 = func1->NewInstance(env.local()).ToLocalChecked();
   26504          25 :     CHECK(env->Global()
   26505             :               ->Set(env.local(), v8_str("instance1"), instance1)
   26506             :               .FromJust());
   26507             :     ExpectFalse("instance1.hasOwnProperty('error_proto')");
   26508             :     ExpectTrue("'error_proto' in instance1.__proto__");
   26509             :     ExpectTrue("instance1.error_proto === Error.prototype");
   26510             :   }
   26511             :   // Put %ErrorPrototype% in a function object's inheritance chain.
   26512             :   {
   26513             :     Local<FunctionTemplate> parent_template =
   26514           5 :         v8::FunctionTemplate::New(isolate);
   26515           5 :     parent_template->RemovePrototype();  // Remove so there is no name clash.
   26516             :     parent_template->SetIntrinsicDataProperty(v8_str("prototype"),
   26517          10 :                                               v8::kErrorPrototype);
   26518           5 :     Local<FunctionTemplate> func_template = v8::FunctionTemplate::New(isolate);
   26519           5 :     func_template->Inherit(parent_template);
   26520             : 
   26521             :     Local<Function> func =
   26522           5 :         func_template->GetFunction(env.local()).ToLocalChecked();
   26523          25 :     CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
   26524             :     ExpectTrue("func.prototype.__proto__ === Error.prototype");
   26525             : 
   26526             :     Local<Object> func_instance =
   26527           5 :         func->NewInstance(env.local()).ToLocalChecked();
   26528          25 :     CHECK(env->Global()
   26529             :               ->Set(env.local(), v8_str("instance"), func_instance)
   26530             :               .FromJust());
   26531             :     ExpectTrue("instance.__proto__.__proto__.__proto__ === Object.prototype");
   26532             :     // Now let's check if %ErrorPrototype% properties are in the instance.
   26533             :     ExpectTrue("'constructor' in instance");
   26534             :     ExpectTrue("'message' in instance");
   26535             :     ExpectTrue("'name' in instance");
   26536             :     ExpectTrue("'toString' in instance");
   26537           5 :   }
   26538           5 : }
   26539             : 
   26540       25880 : TEST(ObjectTemplateArrayProtoIntrinsics) {
   26541           5 :   v8::Isolate* isolate = CcTest::isolate();
   26542           5 :   v8::HandleScope scope(isolate);
   26543          10 :   LocalContext env;
   26544             : 
   26545           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26546             :   object_template->SetIntrinsicDataProperty(v8_str("prop_entries"),
   26547          10 :                                             v8::kArrayProto_entries);
   26548             :   object_template->SetIntrinsicDataProperty(v8_str("prop_forEach"),
   26549          10 :                                             v8::kArrayProto_forEach);
   26550             :   object_template->SetIntrinsicDataProperty(v8_str("prop_keys"),
   26551          10 :                                             v8::kArrayProto_keys);
   26552             :   object_template->SetIntrinsicDataProperty(v8_str("prop_values"),
   26553          10 :                                             v8::kArrayProto_values);
   26554             :   Local<Object> object =
   26555           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26556          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   26557             : 
   26558             :   const struct {
   26559             :     const char* const object_property_name;
   26560             :     const char* const array_property_name;
   26561             :   } intrinsics_comparisons[] = {
   26562             :       {"prop_entries", "Array.prototype.entries"},
   26563             :       {"prop_forEach", "Array.prototype.forEach"},
   26564             :       {"prop_keys", "Array.prototype.keys"},
   26565             :       {"prop_values", "Array.prototype[Symbol.iterator]"},
   26566           5 :   };
   26567             : 
   26568          25 :   for (unsigned i = 0; i < arraysize(intrinsics_comparisons); i++) {
   26569             :     i::ScopedVector<char> test_string(64);
   26570             : 
   26571             :     i::SNPrintF(test_string, "typeof obj1.%s",
   26572          20 :                 intrinsics_comparisons[i].object_property_name);
   26573          20 :     ExpectString(test_string.start(), "function");
   26574             : 
   26575             :     i::SNPrintF(test_string, "obj1.%s === %s",
   26576             :                 intrinsics_comparisons[i].object_property_name,
   26577          20 :                 intrinsics_comparisons[i].array_property_name);
   26578             :     ExpectTrue(test_string.start());
   26579             : 
   26580             :     i::SNPrintF(test_string, "obj1.%s = 42",
   26581          20 :                 intrinsics_comparisons[i].object_property_name);
   26582             :     CompileRun(test_string.start());
   26583             : 
   26584             :     i::SNPrintF(test_string, "obj1.%s === %s",
   26585             :                 intrinsics_comparisons[i].object_property_name,
   26586          20 :                 intrinsics_comparisons[i].array_property_name);
   26587             :     ExpectFalse(test_string.start());
   26588             : 
   26589             :     i::SNPrintF(test_string, "typeof obj1.%s",
   26590          20 :                 intrinsics_comparisons[i].object_property_name);
   26591          20 :     ExpectString(test_string.start(), "number");
   26592           5 :   }
   26593           5 : }
   26594             : 
   26595       25880 : TEST(ObjectTemplatePerContextIntrinsics) {
   26596           5 :   v8::Isolate* isolate = CcTest::isolate();
   26597           5 :   v8::HandleScope scope(isolate);
   26598          10 :   LocalContext env;
   26599             : 
   26600           5 :   Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
   26601             :   object_template->SetIntrinsicDataProperty(v8_str("values"),
   26602          10 :                                             v8::kArrayProto_values);
   26603             :   Local<Object> object =
   26604           5 :       object_template->NewInstance(env.local()).ToLocalChecked();
   26605             : 
   26606          25 :   CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
   26607           5 :   ExpectString("typeof obj1.values", "function");
   26608             : 
   26609             :   auto values = Local<Function>::Cast(
   26610          15 :       object->Get(env.local(), v8_str("values")).ToLocalChecked());
   26611           5 :   auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
   26612          10 :   auto ctx = v8::Utils::OpenHandle(*env.local());
   26613          20 :   CHECK_EQ(*fn->GetCreationContext(), *ctx);
   26614             : 
   26615             :   {
   26616           5 :     LocalContext env2;
   26617             :     Local<Object> object2 =
   26618           5 :         object_template->NewInstance(env2.local()).ToLocalChecked();
   26619          25 :     CHECK(
   26620             :         env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
   26621           5 :     ExpectString("typeof obj2.values", "function");
   26622          25 :     CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
   26623             :              *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   26624             : 
   26625             :     auto values2 = Local<Function>::Cast(
   26626          15 :         object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
   26627           5 :     auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
   26628          10 :     auto ctx2 = v8::Utils::OpenHandle(*env2.local());
   26629          20 :     CHECK_EQ(*fn2->GetCreationContext(), *ctx2);
   26630           5 :   }
   26631           5 : }
   26632             : 
   26633             : 
   26634       25880 : TEST(Proxy) {
   26635           5 :   LocalContext context;
   26636           5 :   v8::Isolate* isolate = CcTest::isolate();
   26637          10 :   v8::HandleScope scope(isolate);
   26638             :   v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
   26639             :   v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
   26640             : 
   26641             :   v8::Local<v8::Proxy> proxy =
   26642           5 :       v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
   26643           5 :   CHECK(proxy->IsProxy());
   26644           5 :   CHECK(!target->IsProxy());
   26645           5 :   CHECK(!proxy->IsRevoked());
   26646          10 :   CHECK(proxy->GetTarget()->SameValue(target));
   26647          10 :   CHECK(proxy->GetHandler()->SameValue(handler));
   26648             : 
   26649           5 :   proxy->Revoke();
   26650           5 :   CHECK(proxy->IsProxy());
   26651           5 :   CHECK(!target->IsProxy());
   26652           5 :   CHECK(proxy->IsRevoked());
   26653          10 :   CHECK(proxy->GetTarget()->IsNull());
   26654          15 :   CHECK(proxy->GetHandler()->IsNull());
   26655           5 : }
   26656             : 
   26657          10 : WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
   26658             :     v8::Isolate* isolate, WeakCallCounter* counter) {
   26659             :   v8::Locker locker(isolate);
   26660          20 :   LocalContext env;
   26661          20 :   HandleScope scope(isolate);
   26662             :   WeakCallCounterAndPersistent<Value>* val =
   26663          10 :       new WeakCallCounterAndPersistent<Value>(counter);
   26664          20 :   val->handle.Reset(isolate, Object::New(isolate));
   26665             :   val->handle.SetWeak(val, &WeakPointerCallback,
   26666             :                       v8::WeakCallbackType::kParameter);
   26667          10 :   return val;
   26668             : }
   26669             : 
   26670           5 : class MemoryPressureThread : public v8::base::Thread {
   26671             :  public:
   26672             :   explicit MemoryPressureThread(v8::Isolate* isolate,
   26673             :                                 v8::MemoryPressureLevel level)
   26674             :       : Thread(Options("MemoryPressureThread")),
   26675             :         isolate_(isolate),
   26676           5 :         level_(level) {}
   26677             : 
   26678           5 :   void Run() override { isolate_->MemoryPressureNotification(level_); }
   26679             : 
   26680             :  private:
   26681             :   v8::Isolate* isolate_;
   26682             :   v8::MemoryPressureLevel level_;
   26683             : };
   26684             : 
   26685       25880 : TEST(MemoryPressure) {
   26686           5 :   if (v8::internal::FLAG_optimize_for_size) return;
   26687           5 :   v8::Isolate* isolate = CcTest::isolate();
   26688             :   WeakCallCounter counter(1234);
   26689             : 
   26690             :   // Check that critical memory pressure notification sets GC interrupt.
   26691           5 :   auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   26692           5 :   CHECK(!v8::Locker::IsLocked(isolate));
   26693             :   {
   26694             :     v8::Locker locker(isolate);
   26695          10 :     v8::HandleScope scope(isolate);
   26696          10 :     LocalContext env;
   26697             :     MemoryPressureThread memory_pressure_thread(
   26698             :         isolate, v8::MemoryPressureLevel::kCritical);
   26699           5 :     memory_pressure_thread.Start();
   26700           5 :     memory_pressure_thread.Join();
   26701             :     // This should trigger GC.
   26702           5 :     CHECK_EQ(0, counter.NumberOfWeakCalls());
   26703             :     CompileRun("(function noop() { return 0; })()");
   26704          10 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   26705             :   }
   26706           5 :   delete garbage;
   26707             :   // Check that critical memory pressure notification triggers GC.
   26708           5 :   garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
   26709             :   {
   26710             :     v8::Locker locker(isolate);
   26711             :     // If isolate is locked, memory pressure notification should trigger GC.
   26712           5 :     CHECK_EQ(1, counter.NumberOfWeakCalls());
   26713           5 :     isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
   26714           5 :     CHECK_EQ(2, counter.NumberOfWeakCalls());
   26715             :   }
   26716           5 :   delete garbage;
   26717             :   // Check that moderate memory pressure notification sets GC into memory
   26718             :   // optimizing mode.
   26719           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
   26720           5 :   CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   26721             :   // Check that disabling memory pressure returns GC into normal mode.
   26722           5 :   isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
   26723           5 :   CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
   26724             : }
   26725             : 
   26726       25880 : TEST(SetIntegrityLevel) {
   26727           5 :   LocalContext context;
   26728           5 :   v8::Isolate* isolate = CcTest::isolate();
   26729          10 :   v8::HandleScope scope(isolate);
   26730             : 
   26731           5 :   v8::Local<v8::Object> obj = v8::Object::New(isolate);
   26732          25 :   CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
   26733             : 
   26734             :   v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
   26735           5 :   CHECK(!is_frozen->BooleanValue(isolate));
   26736             : 
   26737          10 :   CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
   26738             :             .FromJust());
   26739             : 
   26740             :   is_frozen = CompileRun("Object.isFrozen(o)");
   26741          10 :   CHECK(is_frozen->BooleanValue(isolate));
   26742           5 : }
   26743             : 
   26744       25880 : TEST(PrivateForApiIsNumber) {
   26745           5 :   LocalContext context;
   26746           5 :   v8::Isolate* isolate = CcTest::isolate();
   26747          10 :   v8::HandleScope scope(isolate);
   26748             : 
   26749             :   // Shouldn't crash.
   26750          10 :   v8::Private::ForApi(isolate, v8_str("42"));
   26751           5 : }
   26752             : 
   26753       25881 : THREADED_TEST(ImmutableProto) {
   26754           6 :   LocalContext context;
   26755           6 :   v8::Isolate* isolate = context->GetIsolate();
   26756          12 :   v8::HandleScope handle_scope(isolate);
   26757             : 
   26758           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   26759          12 :   templ->InstanceTemplate()->SetImmutableProto();
   26760             : 
   26761           6 :   Local<v8::Object> object = templ->GetFunction(context.local())
   26762           6 :                                  .ToLocalChecked()
   26763           6 :                                  ->NewInstance(context.local())
   26764             :                                  .ToLocalChecked();
   26765             : 
   26766             :   // Look up the prototype
   26767             :   Local<v8::Value> original_proto =
   26768          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26769             : 
   26770             :   // Setting the prototype (e.g., to null) throws
   26771          12 :   CHECK(object->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   26772             : 
   26773             :   // The original prototype is still there
   26774             :   Local<Value> new_proto =
   26775          18 :       object->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26776           6 :   CHECK(new_proto->IsObject());
   26777          12 :   CHECK(new_proto.As<v8::Object>()
   26778             :             ->Equals(context.local(), original_proto)
   26779           6 :             .FromJust());
   26780           6 : }
   26781             : 
   26782             : Local<v8::Context> call_eval_context;
   26783             : Local<v8::Function> call_eval_bound_function;
   26784             : 
   26785          10 : static void CallEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
   26786             :   v8::Context::Scope scope(call_eval_context);
   26787             :   args.GetReturnValue().Set(
   26788             :       call_eval_bound_function
   26789          10 :           ->Call(call_eval_context, call_eval_context->Global(), 0, nullptr)
   26790           5 :           .ToLocalChecked());
   26791           5 : }
   26792             : 
   26793       25880 : TEST(CrossActivationEval) {
   26794           5 :   LocalContext env;
   26795           5 :   v8::Isolate* isolate = env->GetIsolate();
   26796          10 :   v8::HandleScope scope(isolate);
   26797             :   {
   26798           5 :     call_eval_context = v8::Context::New(isolate);
   26799             :     v8::Context::Scope scope(call_eval_context);
   26800             :     call_eval_bound_function =
   26801           5 :         Local<Function>::Cast(CompileRun("eval.bind(this, '1')"));
   26802             :   }
   26803             :   env->Global()
   26804             :       ->Set(env.local(), v8_str("CallEval"),
   26805           5 :             v8::FunctionTemplate::New(isolate, CallEval)
   26806          15 :                 ->GetFunction(env.local())
   26807          25 :                 .ToLocalChecked())
   26808          10 :       .FromJust();
   26809             :   Local<Value> result = CompileRun("CallEval();");
   26810           5 :   CHECK(result->IsInt32());
   26811          15 :   CHECK_EQ(1, result->Int32Value(env.local()).FromJust());
   26812           5 : }
   26813             : 
   26814       25880 : TEST(EvalInAccessCheckedContext) {
   26815           5 :   v8::Isolate* isolate = CcTest::isolate();
   26816           5 :   v8::HandleScope scope(isolate);
   26817             : 
   26818           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   26819             : 
   26820           5 :   obj_template->SetAccessCheckCallback(AccessAlwaysAllowed);
   26821             : 
   26822           5 :   v8::Local<Context> context0 = Context::New(isolate, nullptr, obj_template);
   26823           5 :   v8::Local<Context> context1 = Context::New(isolate, nullptr, obj_template);
   26824             : 
   26825           5 :   Local<Value> foo = v8_str("foo");
   26826           5 :   Local<Value> bar = v8_str("bar");
   26827             : 
   26828             :   // Set to different domains.
   26829           5 :   context0->SetSecurityToken(foo);
   26830           5 :   context1->SetSecurityToken(bar);
   26831             : 
   26832             :   // Set up function in context0 that uses eval from context0.
   26833           5 :   context0->Enter();
   26834             :   v8::Local<v8::Value> fun = CompileRun(
   26835             :       "var x = 42;"
   26836             :       "(function() {"
   26837             :       "  var e = eval;"
   26838             :       "  return function(s) { return e(s); }"
   26839           5 :       "})()");
   26840           5 :   context0->Exit();
   26841             : 
   26842             :   // Put the function into context1 and call it. Since the access check
   26843             :   // callback always returns true, the call succeeds even though the tokens
   26844             :   // are different.
   26845           5 :   context1->Enter();
   26846          20 :   context1->Global()->Set(context1, v8_str("fun"), fun).FromJust();
   26847             :   v8::Local<v8::Value> x_value = CompileRun("fun('x')");
   26848          10 :   CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
   26849           5 :   context1->Exit();
   26850           5 : }
   26851             : 
   26852       25881 : THREADED_TEST(ImmutableProtoWithParent) {
   26853           6 :   LocalContext context;
   26854           6 :   v8::Isolate* isolate = context->GetIsolate();
   26855          12 :   v8::HandleScope handle_scope(isolate);
   26856             : 
   26857           6 :   Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate);
   26858             : 
   26859           6 :   Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
   26860           6 :   templ->Inherit(parent);
   26861          12 :   templ->PrototypeTemplate()->SetImmutableProto();
   26862             : 
   26863             :   Local<v8::Function> function =
   26864           6 :       templ->GetFunction(context.local()).ToLocalChecked();
   26865             :   Local<v8::Object> instance =
   26866           6 :       function->NewInstance(context.local()).ToLocalChecked();
   26867             :   Local<v8::Object> prototype =
   26868          18 :       instance->Get(context.local(), v8_str("__proto__"))
   26869           6 :           .ToLocalChecked()
   26870           6 :           ->ToObject(context.local())
   26871           6 :           .ToLocalChecked();
   26872             : 
   26873             :   // Look up the prototype
   26874             :   Local<v8::Value> original_proto =
   26875          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26876             : 
   26877             :   // Setting the prototype (e.g., to null) throws
   26878          12 :   CHECK(
   26879             :       prototype->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
   26880             : 
   26881             :   // The original prototype is still there
   26882             :   Local<Value> new_proto =
   26883          18 :       prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
   26884           6 :   CHECK(new_proto->IsObject());
   26885          12 :   CHECK(new_proto.As<v8::Object>()
   26886             :             ->Equals(context.local(), original_proto)
   26887           6 :             .FromJust());
   26888           6 : }
   26889             : 
   26890       25880 : TEST(InternalFieldsOnGlobalProxy) {
   26891           5 :   v8::Isolate* isolate = CcTest::isolate();
   26892           5 :   v8::HandleScope scope(isolate);
   26893             : 
   26894           5 :   v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
   26895           5 :   obj_template->SetInternalFieldCount(1);
   26896             : 
   26897           5 :   v8::Local<v8::Context> context = Context::New(isolate, nullptr, obj_template);
   26898           5 :   v8::Local<v8::Object> global = context->Global();
   26899           5 :   CHECK_EQ(1, global->InternalFieldCount());
   26900           5 : }
   26901             : 
   26902       25881 : THREADED_TEST(ImmutableProtoGlobal) {
   26903           6 :   v8::Isolate* isolate = CcTest::isolate();
   26904           6 :   v8::HandleScope handle_scope(isolate);
   26905           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   26906           6 :   global_template->SetImmutableProto();
   26907           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
   26908             :   Context::Scope context_scope(context);
   26909             :   v8::Local<Value> result = CompileRun(
   26910             :       "global = this;"
   26911             :       "(function() {"
   26912             :       "  try {"
   26913             :       "    global.__proto__ = {};"
   26914             :       "    return 0;"
   26915             :       "  } catch (e) {"
   26916             :       "    return 1;"
   26917             :       "  }"
   26918             :       "})()");
   26919          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 1))
   26920           6 :             .FromJust());
   26921           6 : }
   26922             : 
   26923       25881 : THREADED_TEST(MutableProtoGlobal) {
   26924           6 :   v8::Isolate* isolate = CcTest::isolate();
   26925           6 :   v8::HandleScope handle_scope(isolate);
   26926           6 :   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
   26927           6 :   v8::Local<Context> context = Context::New(isolate, nullptr, global_template);
   26928             :   Context::Scope context_scope(context);
   26929             :   v8::Local<Value> result = CompileRun(
   26930             :       "global = this;"
   26931             :       "(function() {"
   26932             :       "  try {"
   26933             :       "    global.__proto__ = {};"
   26934             :       "    return 0;"
   26935             :       "  } catch (e) {"
   26936             :       "    return 1;"
   26937             :       "  }"
   26938             :       "})()");
   26939          18 :   CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 0))
   26940           6 :             .FromJust());
   26941           6 : }
   26942             : 
   26943       25880 : TEST(InternalFieldsOnTypedArray) {
   26944           5 :   LocalContext env;
   26945           5 :   v8::Isolate* isolate = env->GetIsolate();
   26946          10 :   v8::HandleScope scope(isolate);
   26947           5 :   v8::Local<v8::Context> context = env.local();
   26948             :   Context::Scope context_scope(context);
   26949           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   26950           5 :   v8::Local<v8::Uint8Array> array = v8::Uint8Array::New(buffer, 0, 1);
   26951          15 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   26952          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   26953             :              array->GetAlignedPointerFromInternalField(i));
   26954           5 :   }
   26955           5 : }
   26956             : 
   26957       25880 : TEST(InternalFieldsOnDataView) {
   26958           5 :   LocalContext env;
   26959           5 :   v8::Isolate* isolate = env->GetIsolate();
   26960          10 :   v8::HandleScope scope(isolate);
   26961           5 :   v8::Local<v8::Context> context = env.local();
   26962             :   Context::Scope context_scope(context);
   26963           5 :   v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1);
   26964           5 :   v8::Local<v8::DataView> array = v8::DataView::New(buffer, 0, 1);
   26965          15 :   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
   26966          10 :     CHECK_EQ(static_cast<void*>(nullptr),
   26967             :              array->GetAlignedPointerFromInternalField(i));
   26968           5 :   }
   26969           5 : }
   26970             : 
   26971       25880 : TEST(SetPrototypeTemplate) {
   26972           5 :   LocalContext env;
   26973           5 :   v8::Isolate* isolate = env->GetIsolate();
   26974          10 :   v8::HandleScope scope(isolate);
   26975             : 
   26976           5 :   Local<FunctionTemplate> HTMLElementTemplate = FunctionTemplate::New(isolate);
   26977             :   Local<FunctionTemplate> HTMLImageElementTemplate =
   26978           5 :       FunctionTemplate::New(isolate);
   26979           5 :   HTMLImageElementTemplate->Inherit(HTMLElementTemplate);
   26980             : 
   26981           5 :   Local<FunctionTemplate> ImageTemplate = FunctionTemplate::New(isolate);
   26982           5 :   ImageTemplate->SetPrototypeProviderTemplate(HTMLImageElementTemplate);
   26983             : 
   26984             :   Local<Function> HTMLImageElement =
   26985           5 :       HTMLImageElementTemplate->GetFunction(env.local()).ToLocalChecked();
   26986             :   Local<Function> Image =
   26987           5 :       ImageTemplate->GetFunction(env.local()).ToLocalChecked();
   26988             : 
   26989          25 :   CHECK(env->Global()
   26990             :             ->Set(env.local(), v8_str("HTMLImageElement"), HTMLImageElement)
   26991             :             .FromJust());
   26992          25 :   CHECK(env->Global()->Set(env.local(), v8_str("Image"), Image).FromJust());
   26993             : 
   26994           5 :   ExpectTrue("Image.prototype === HTMLImageElement.prototype");
   26995           5 : }
   26996             : 
   26997         120 : void ensure_receiver_is_global_proxy(
   26998             :     v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
   26999         240 :   CHECK(v8::Utils::OpenHandle(*info.This())->IsJSGlobalProxy());
   27000         120 : }
   27001             : 
   27002       25881 : THREADED_TEST(GlobalAccessorInfo) {
   27003           6 :   v8::Isolate* isolate = CcTest::isolate();
   27004           6 :   v8::HandleScope scope(isolate);
   27005           6 :   Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
   27006             :   global_template->SetAccessor(
   27007             :       v8::String::NewFromUtf8(isolate, "prop", v8::NewStringType::kInternalized)
   27008             :           .ToLocalChecked(),
   27009          12 :       &ensure_receiver_is_global_proxy);
   27010          12 :   LocalContext env(nullptr, global_template);
   27011             :   CompileRun("for (var i = 0; i < 10; i++) this.prop");
   27012           6 :   CompileRun("for (var i = 0; i < 10; i++) prop");
   27013           6 : }
   27014             : 
   27015       25880 : TEST(DeterministicRandomNumberGeneration) {
   27016           5 :   v8::HandleScope scope(CcTest::isolate());
   27017             : 
   27018           5 :   int previous_seed = v8::internal::FLAG_random_seed;
   27019           5 :   v8::internal::FLAG_random_seed = 1234;
   27020             : 
   27021             :   double first_value;
   27022             :   double second_value;
   27023             :   {
   27024           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27025             :     Context::Scope context_scope(context);
   27026             :     v8::Local<Value> result = CompileRun("Math.random();");
   27027          10 :     first_value = result->ToNumber(context).ToLocalChecked()->Value();
   27028             :   }
   27029             :   {
   27030           5 :     v8::Local<Context> context = Context::New(CcTest::isolate());
   27031             :     Context::Scope context_scope(context);
   27032             :     v8::Local<Value> result = CompileRun("Math.random();");
   27033          10 :     second_value = result->ToNumber(context).ToLocalChecked()->Value();
   27034             :   }
   27035           5 :   CHECK_EQ(first_value, second_value);
   27036             : 
   27037           5 :   v8::internal::FLAG_random_seed = previous_seed;
   27038           5 : }
   27039             : 
   27040       25880 : UNINITIALIZED_TEST(AllowAtomicsWait) {
   27041             :   v8::Isolate::CreateParams create_params;
   27042           5 :   create_params.allow_atomics_wait = false;
   27043           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   27044           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
   27045          10 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27046             :   {
   27047           5 :     CHECK_EQ(false, i_isolate->allow_atomics_wait());
   27048           5 :     isolate->SetAllowAtomicsWait(true);
   27049           5 :     CHECK_EQ(true, i_isolate->allow_atomics_wait());
   27050             :   }
   27051           5 :   isolate->Dispose();
   27052           5 : }
   27053             : 
   27054             : enum ContextId { EnteredContext, CurrentContext };
   27055             : 
   27056          20 : void CheckContexts(v8::Isolate* isolate) {
   27057          60 :   CHECK_EQ(CurrentContext, isolate->GetCurrentContext()
   27058             :                                ->GetEmbedderData(1)
   27059             :                                .As<v8::Integer>()
   27060             :                                ->Value());
   27061          60 :   CHECK_EQ(EnteredContext, isolate->GetEnteredOrMicrotaskContext()
   27062             :                                ->GetEmbedderData(1)
   27063             :                                .As<v8::Integer>()
   27064             :                                ->Value());
   27065          20 : }
   27066             : 
   27067           5 : void ContextCheckGetter(Local<String> name,
   27068             :                         const v8::PropertyCallbackInfo<v8::Value>& info) {
   27069           5 :   CheckContexts(info.GetIsolate());
   27070             :   info.GetReturnValue().Set(true);
   27071           5 : }
   27072             : 
   27073           5 : void ContextCheckSetter(Local<String> name, Local<Value>,
   27074             :                         const v8::PropertyCallbackInfo<void>& info) {
   27075           5 :   CheckContexts(info.GetIsolate());
   27076           5 : }
   27077             : 
   27078          20 : void ContextCheckToString(const v8::FunctionCallbackInfo<v8::Value>& info) {
   27079          10 :   CheckContexts(info.GetIsolate());
   27080          10 :   info.GetReturnValue().Set(v8_str("foo"));
   27081          10 : }
   27082             : 
   27083       25880 : TEST(CorrectEnteredContext) {
   27084           5 :   v8::HandleScope scope(CcTest::isolate());
   27085             : 
   27086          10 :   LocalContext currentContext;
   27087             :   currentContext->SetEmbedderData(
   27088          10 :       1, v8::Integer::New(currentContext->GetIsolate(), CurrentContext));
   27089          10 :   LocalContext enteredContext;
   27090             :   enteredContext->SetEmbedderData(
   27091          10 :       1, v8::Integer::New(enteredContext->GetIsolate(), EnteredContext));
   27092             : 
   27093           5 :   v8::Context::Scope contextScope(enteredContext.local());
   27094             : 
   27095             :   v8::Local<v8::ObjectTemplate> object_template =
   27096           5 :       ObjectTemplate::New(currentContext->GetIsolate());
   27097             :   object_template->SetAccessor(v8_str("p"), &ContextCheckGetter,
   27098           5 :                                &ContextCheckSetter);
   27099             : 
   27100             :   v8::Local<v8::Object> object =
   27101           5 :       object_template->NewInstance(currentContext.local()).ToLocalChecked();
   27102             : 
   27103          15 :   object->Get(currentContext.local(), v8_str("p")).ToLocalChecked();
   27104          15 :   object->Set(currentContext.local(), v8_str("p"), v8_int(0)).FromJust();
   27105             : 
   27106             :   v8::Local<v8::Function> to_string =
   27107          10 :       v8::Function::New(currentContext.local(), ContextCheckToString)
   27108           5 :           .ToLocalChecked();
   27109             : 
   27110          10 :   to_string->Call(currentContext.local(), object, 0, nullptr).ToLocalChecked();
   27111             : 
   27112             :   object
   27113             :       ->CreateDataProperty(currentContext.local(), v8_str("toString"),
   27114          15 :                            to_string)
   27115          10 :       .FromJust();
   27116             : 
   27117          10 :   object->ToString(currentContext.local()).ToLocalChecked();
   27118           5 : }
   27119             : 
   27120           5 : v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallbackResolve(
   27121             :     Local<Context> context, Local<v8::ScriptOrModule> referrer,
   27122             :     Local<String> specifier) {
   27123           5 :   CHECK(!referrer.IsEmpty());
   27124             :   String::Utf8Value referrer_utf8(
   27125          10 :       context->GetIsolate(), Local<String>::Cast(referrer->GetResourceName()));
   27126           5 :   CHECK_EQ(0, strcmp("www.google.com", *referrer_utf8));
   27127          15 :   CHECK(referrer->GetHostDefinedOptions()
   27128             :             ->Get(context->GetIsolate(), 0)
   27129             :             ->IsSymbol());
   27130             : 
   27131           5 :   CHECK(!specifier.IsEmpty());
   27132          10 :   String::Utf8Value specifier_utf8(context->GetIsolate(), specifier);
   27133           5 :   CHECK_EQ(0, strcmp("index.js", *specifier_utf8));
   27134             : 
   27135             :   Local<v8::Promise::Resolver> resolver =
   27136           5 :       v8::Promise::Resolver::New(context).ToLocalChecked();
   27137           5 :   auto result = v8_str("hello world");
   27138          10 :   resolver->Resolve(context, result).ToChecked();
   27139          10 :   return resolver->GetPromise();
   27140             : }
   27141             : 
   27142       25880 : TEST(DynamicImport) {
   27143           5 :   i::FLAG_harmony_dynamic_import = true;
   27144           5 :   LocalContext context;
   27145           5 :   v8::Isolate* isolate = context->GetIsolate();
   27146          10 :   v8::HandleScope scope(isolate);
   27147             : 
   27148             :   isolate->SetHostImportModuleDynamicallyCallback(
   27149           5 :       HostImportModuleDynamicallyCallbackResolve);
   27150             : 
   27151          10 :   i::Handle<i::String> url(v8::Utils::OpenHandle(*v8_str("www.google.com")));
   27152          10 :   i::Handle<i::Object> specifier(v8::Utils::OpenHandle(*v8_str("index.js")));
   27153          10 :   i::Handle<i::String> result(v8::Utils::OpenHandle(*v8_str("hello world")));
   27154          10 :   i::Handle<i::String> source(v8::Utils::OpenHandle(*v8_str("foo")));
   27155             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27156           5 :   i::Handle<i::FixedArray> options = i_isolate->factory()->NewFixedArray(1);
   27157           5 :   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewSymbol();
   27158          10 :   options->set(0, *symbol);
   27159           5 :   i::Handle<i::Script> referrer = i_isolate->factory()->NewScript(source);
   27160          10 :   referrer->set_name(*url);
   27161           5 :   referrer->set_host_defined_options(*options);
   27162             :   i::MaybeHandle<i::JSPromise> maybe_promise =
   27163           5 :       i_isolate->RunHostImportModuleDynamicallyCallback(referrer, specifier);
   27164             :   i::Handle<i::JSPromise> promise = maybe_promise.ToHandleChecked();
   27165           5 :   isolate->RunMicrotasks();
   27166          10 :   CHECK(result->Equals(i::String::cast(promise->result())));
   27167           5 : }
   27168             : 
   27169           5 : void HostInitializeImportMetaObjectCallbackStatic(Local<Context> context,
   27170             :                                                   Local<Module> module,
   27171             :                                                   Local<Object> meta) {
   27172           5 :   CHECK(!module.IsEmpty());
   27173             : 
   27174          20 :   meta->CreateDataProperty(context, v8_str("foo"), v8_str("bar")).ToChecked();
   27175           5 : }
   27176             : 
   27177       25880 : TEST(ImportMeta) {
   27178           5 :   i::FLAG_harmony_dynamic_import = true;
   27179           5 :   i::FLAG_harmony_import_meta = true;
   27180           5 :   LocalContext context;
   27181           5 :   v8::Isolate* isolate = context->GetIsolate();
   27182          10 :   v8::HandleScope scope(isolate);
   27183             : 
   27184             :   isolate->SetHostInitializeImportMetaObjectCallback(
   27185           5 :       HostInitializeImportMetaObjectCallbackStatic);
   27186             : 
   27187             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27188           5 :   Local<String> url = v8_str("www.google.com");
   27189           5 :   Local<String> source_text = v8_str("import.meta;");
   27190             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27191             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27192             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27193             :                           Local<v8::Boolean>(), True(isolate));
   27194             :   v8::ScriptCompiler::Source source(source_text, origin);
   27195             :   Local<Module> module =
   27196           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27197             :   i::Handle<i::Object> meta =
   27198             :       i_isolate->RunHostInitializeImportMetaObjectCallback(
   27199           5 :           v8::Utils::OpenHandle(*module));
   27200          10 :   CHECK(meta->IsJSObject());
   27201             :   Local<Object> meta_obj = Local<Object>::Cast(v8::Utils::ToLocal(meta));
   27202          15 :   CHECK(meta_obj->Get(context.local(), v8_str("foo"))
   27203             :             .ToLocalChecked()
   27204             :             ->IsString());
   27205          15 :   CHECK(meta_obj->Get(context.local(), v8_str("zapp"))
   27206             :             .ToLocalChecked()
   27207             :             ->IsUndefined());
   27208             : 
   27209           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27210          10 :       .ToChecked();
   27211           5 :   Local<Value> result = module->Evaluate(context.local()).ToLocalChecked();
   27212          10 :   CHECK(result->StrictEquals(Local<v8::Value>::Cast(v8::Utils::ToLocal(meta))));
   27213           5 : }
   27214             : 
   27215       25880 : TEST(GetModuleNamespace) {
   27216           5 :   LocalContext context;
   27217           5 :   v8::Isolate* isolate = context->GetIsolate();
   27218          10 :   v8::HandleScope scope(isolate);
   27219             : 
   27220           5 :   Local<String> url = v8_str("www.google.com");
   27221           5 :   Local<String> source_text = v8_str("export default 5; export const a = 10;");
   27222             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27223             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27224             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27225             :                           Local<v8::Boolean>(), True(isolate));
   27226             :   v8::ScriptCompiler::Source source(source_text, origin);
   27227             :   Local<Module> module =
   27228           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27229           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27230          10 :       .ToChecked();
   27231           5 :   module->Evaluate(context.local()).ToLocalChecked();
   27232             : 
   27233           5 :   Local<Value> ns_val = module->GetModuleNamespace();
   27234           5 :   CHECK(ns_val->IsModuleNamespaceObject());
   27235             :   Local<Object> ns = ns_val.As<Object>();
   27236          20 :   CHECK(ns->Get(context.local(), v8_str("default"))
   27237             :             .ToLocalChecked()
   27238             :             ->StrictEquals(v8::Number::New(isolate, 5)));
   27239          20 :   CHECK(ns->Get(context.local(), v8_str("a"))
   27240             :             .ToLocalChecked()
   27241           5 :             ->StrictEquals(v8::Number::New(isolate, 10)));
   27242           5 : }
   27243             : 
   27244       25880 : TEST(ModuleGetUnboundModuleScript) {
   27245           5 :   LocalContext context;
   27246           5 :   v8::Isolate* isolate = context->GetIsolate();
   27247          10 :   v8::HandleScope scope(isolate);
   27248             : 
   27249           5 :   Local<String> url = v8_str("www.google.com");
   27250           5 :   Local<String> source_text = v8_str("export default 5; export const a = 10;");
   27251             :   v8::ScriptOrigin origin(url, Local<v8::Integer>(), Local<v8::Integer>(),
   27252             :                           Local<v8::Boolean>(), Local<v8::Integer>(),
   27253             :                           Local<v8::Value>(), Local<v8::Boolean>(),
   27254             :                           Local<v8::Boolean>(), True(isolate));
   27255             :   v8::ScriptCompiler::Source source(source_text, origin);
   27256             :   Local<Module> module =
   27257           5 :       v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
   27258             :   Local<v8::UnboundModuleScript> sfi_before_instantiation =
   27259           5 :       module->GetUnboundModuleScript();
   27260           5 :   module->InstantiateModule(context.local(), UnexpectedModuleResolveCallback)
   27261          10 :       .ToChecked();
   27262             :   Local<v8::UnboundModuleScript> sfi_after_instantiation =
   27263           5 :       module->GetUnboundModuleScript();
   27264             : 
   27265             :   // Check object identity.
   27266             :   {
   27267             :     i::Handle<i::Object> s1 = v8::Utils::OpenHandle(*sfi_before_instantiation);
   27268             :     i::Handle<i::Object> s2 = v8::Utils::OpenHandle(*sfi_after_instantiation);
   27269          15 :     CHECK_EQ(*s1, *s2);
   27270           5 :   }
   27271           5 : }
   27272             : 
   27273       25880 : TEST(GlobalTemplateWithDoubleProperty) {
   27274           5 :   v8::Isolate* isolate = CcTest::isolate();
   27275           5 :   v8::HandleScope handle_scope(isolate);
   27276             : 
   27277           5 :   v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
   27278          15 :   global->Set(v8_str("double"), v8_num(3.14));
   27279             : 
   27280           5 :   v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
   27281             : 
   27282             :   v8::Context::Scope context_scope(context);
   27283             : 
   27284             :   Local<Value> result = CompileRun("double");
   27285           5 :   CHECK(result->IsNumber());
   27286          15 :   CheckDoubleEquals(3.14, result->NumberValue(context).ToChecked());
   27287           5 : }
   27288             : 
   27289       25880 : TEST(PrimitiveArray) {
   27290           5 :   v8::Isolate* isolate = CcTest::isolate();
   27291           5 :   v8::HandleScope scope(isolate);
   27292          10 :   LocalContext env;
   27293             : 
   27294             :   int length = 5;
   27295           5 :   Local<v8::PrimitiveArray> array(v8::PrimitiveArray::New(isolate, 5));
   27296           5 :   CHECK_EQ(length, array->Length());
   27297             : 
   27298          25 :   for (int i = 0; i < length; i++) {
   27299          25 :     Local<v8::Primitive> item = array->Get(isolate, i);
   27300          25 :     CHECK(item->IsUndefined());
   27301             :   }
   27302             : 
   27303           5 :   Local<v8::Symbol> symbol(v8::Symbol::New(isolate));
   27304           5 :   array->Set(isolate, 0, symbol);
   27305          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27306             : 
   27307             :   Local<v8::String> string =
   27308             :       v8::String::NewFromUtf8(isolate, "test", v8::NewStringType::kInternalized)
   27309           5 :           .ToLocalChecked();
   27310           5 :   array->Set(isolate, 1, string);
   27311          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27312          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27313             : 
   27314           5 :   Local<v8::Number> num = v8::Number::New(env->GetIsolate(), 3.1415926);
   27315           5 :   array->Set(isolate, 2, num);
   27316          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27317          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27318          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   27319             : 
   27320             :   v8::Local<v8::Boolean> f = v8::False(isolate);
   27321           5 :   array->Set(isolate, 3, f);
   27322          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27323          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27324          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   27325          10 :   CHECK(array->Get(isolate, 3)->IsBoolean());
   27326             : 
   27327           5 :   v8::Local<v8::Primitive> n = v8::Null(isolate);
   27328           5 :   array->Set(isolate, 4, n);
   27329          10 :   CHECK(array->Get(isolate, 0)->IsSymbol());
   27330          10 :   CHECK(array->Get(isolate, 1)->IsString());
   27331          10 :   CHECK(array->Get(isolate, 2)->IsNumber());
   27332          10 :   CHECK(array->Get(isolate, 3)->IsBoolean());
   27333          15 :   CHECK(array->Get(isolate, 4)->IsNull());
   27334           5 : }
   27335             : 
   27336       25880 : TEST(PersistentValueMap) {
   27337           5 :   v8::Isolate* isolate = CcTest::isolate();
   27338           5 :   v8::HandleScope scope(isolate);
   27339          10 :   LocalContext env;
   27340             : 
   27341             :   v8::PersistentValueMap<
   27342             :       std::string, v8::Value,
   27343             :       v8::DefaultPersistentValueMapTraits<std::string, v8::Value>>
   27344             :       map(isolate);
   27345             :   v8::Local<v8::Value> value =
   27346             :       v8::String::NewFromUtf8(isolate, "value",
   27347             :                               v8::NewStringType::kInternalized)
   27348           5 :           .ToLocalChecked();
   27349          20 :   map.Set("key", value);
   27350           5 : }
   27351             : 
   27352             : namespace {
   27353             : 
   27354             : bool wasm_streaming_callback_got_called = false;
   27355             : bool wasm_streaming_data_got_collected = false;
   27356             : 
   27357           8 : void WasmStreamingTestFinalizer(const v8::WeakCallbackInfo<void>& data) {
   27358           4 :   CHECK(!wasm_streaming_data_got_collected);
   27359           4 :   wasm_streaming_data_got_collected = true;
   27360           4 :   i::GlobalHandles::Destroy(reinterpret_cast<i::Address*>(data.GetParameter()));
   27361           4 : }
   27362             : 
   27363           4 : void WasmStreamingCallbackTestCallbackIsCalled(
   27364           8 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27365           4 :   CHECK(!wasm_streaming_callback_got_called);
   27366           4 :   wasm_streaming_callback_got_called = true;
   27367             : 
   27368             :   i::Handle<i::Object> global_handle =
   27369             :       reinterpret_cast<i::Isolate*>(args.GetIsolate())
   27370             :           ->global_handles()
   27371           4 :           ->Create(*v8::Utils::OpenHandle(*args.Data()));
   27372             :   i::GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
   27373             :                              WasmStreamingTestFinalizer,
   27374           4 :                              v8::WeakCallbackType::kParameter);
   27375           4 : }
   27376             : 
   27377           4 : void WasmStreamingCallbackTestOnBytesReceived(
   27378           4 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27379             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27380           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27381             : 
   27382             :   // The first bytes of the WebAssembly magic word.
   27383           4 :   const uint8_t bytes[]{0x00, 0x61, 0x73};
   27384           4 :   streaming->OnBytesReceived(bytes, arraysize(bytes));
   27385           4 : }
   27386             : 
   27387           4 : void WasmStreamingCallbackTestFinishWithSuccess(
   27388           4 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27389             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27390           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27391             :   // The bytes of a minimal WebAssembly module.
   27392           4 :   const uint8_t bytes[]{0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00};
   27393           4 :   streaming->OnBytesReceived(bytes, arraysize(bytes));
   27394           4 :   streaming->Finish();
   27395           4 : }
   27396             : 
   27397           4 : void WasmStreamingCallbackTestFinishWithFailure(
   27398           4 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27399             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27400           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27401           4 :   streaming->Finish();
   27402           4 : }
   27403             : 
   27404           4 : void WasmStreamingCallbackTestAbortWithReject(
   27405           8 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27406             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27407           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27408           8 :   streaming->Abort(v8::Object::New(args.GetIsolate()));
   27409           4 : }
   27410             : 
   27411           4 : void WasmStreamingCallbackTestAbortNoReject(
   27412           4 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
   27413             :   std::shared_ptr<v8::WasmStreaming> streaming =
   27414           4 :       v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
   27415           4 :   streaming->Abort({});
   27416           4 : }
   27417             : 
   27418          24 : void TestWasmStreaming(v8::WasmStreamingCallback callback,
   27419             :                        v8::Promise::PromiseState expected_state) {
   27420          24 :   CcTest::isolate()->SetWasmStreamingCallback(callback);
   27421          24 :   LocalContext env;
   27422          24 :   v8::Isolate* isolate = env->GetIsolate();
   27423          48 :   v8::HandleScope scope(isolate);
   27424             : 
   27425             :   // Call {WebAssembly.compileStreaming} with {null} as parameter. The parameter
   27426             :   // is only really processed by the embedder, so for this test the value is
   27427             :   // irrelevant.
   27428             :   v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(
   27429             :       CompileRun("WebAssembly.compileStreaming(null)"));
   27430             : 
   27431          24 :   EmptyMessageQueues(isolate);
   27432          48 :   CHECK_EQ(expected_state, promise->State());
   27433          24 : }
   27434             : 
   27435             : }  // namespace
   27436             : 
   27437       25879 : TEST(WasmStreamingCallback) {
   27438             :   TestWasmStreaming(WasmStreamingCallbackTestCallbackIsCalled,
   27439           4 :                     v8::Promise::kPending);
   27440           4 :   CHECK(wasm_streaming_callback_got_called);
   27441           4 :   CcTest::CollectAllAvailableGarbage();
   27442           4 :   CHECK(wasm_streaming_data_got_collected);
   27443           4 : }
   27444             : 
   27445       25879 : TEST(WasmStreamingOnBytesReceived) {
   27446             :   TestWasmStreaming(WasmStreamingCallbackTestOnBytesReceived,
   27447           4 :                     v8::Promise::kPending);
   27448           4 : }
   27449             : 
   27450       25879 : TEST(WasmStreamingFinishWithSuccess) {
   27451             :   TestWasmStreaming(WasmStreamingCallbackTestFinishWithSuccess,
   27452           4 :                     v8::Promise::kFulfilled);
   27453           4 : }
   27454             : 
   27455       25879 : TEST(WasmStreamingFinishWithFailure) {
   27456             :   TestWasmStreaming(WasmStreamingCallbackTestFinishWithFailure,
   27457           4 :                     v8::Promise::kRejected);
   27458           4 : }
   27459             : 
   27460       25879 : TEST(WasmStreamingAbortWithReject) {
   27461             :   TestWasmStreaming(WasmStreamingCallbackTestAbortWithReject,
   27462           4 :                     v8::Promise::kRejected);
   27463           4 : }
   27464             : 
   27465       25879 : TEST(WasmStreamingAbortWithoutReject) {
   27466             :   TestWasmStreaming(WasmStreamingCallbackTestAbortNoReject,
   27467           4 :                     v8::Promise::kPending);
   27468           4 : }
   27469             : 
   27470             : enum class AtomicsWaitCallbackAction {
   27471             :   Interrupt,
   27472             :   StopAndThrowInFirstCall,
   27473             :   StopAndThrowInSecondCall,
   27474             :   StopFromThreadAndThrow,
   27475             :   KeepWaiting
   27476             : };
   27477             : 
   27478             : class StopAtomicsWaitThread;
   27479             : 
   27480          10 : struct AtomicsWaitCallbackInfo {
   27481             :   v8::Isolate* isolate;
   27482             :   v8::Isolate::AtomicsWaitWakeHandle* wake_handle;
   27483             :   std::unique_ptr<StopAtomicsWaitThread> stop_thread;
   27484             :   AtomicsWaitCallbackAction action;
   27485             : 
   27486             :   Local<v8::SharedArrayBuffer> expected_sab;
   27487             :   v8::Isolate::AtomicsWaitEvent expected_event;
   27488             :   double expected_timeout;
   27489             :   int64_t expected_value;
   27490             :   size_t expected_offset;
   27491             : 
   27492             :   size_t ncalls = 0;
   27493             : };
   27494             : 
   27495           5 : class StopAtomicsWaitThread : public v8::base::Thread {
   27496             :  public:
   27497             :   explicit StopAtomicsWaitThread(AtomicsWaitCallbackInfo* info)
   27498           5 :       : Thread(Options("StopAtomicsWaitThread")), info_(info) {}
   27499             : 
   27500           5 :   void Run() override {
   27501           5 :     CHECK_NOT_NULL(info_->wake_handle);
   27502           5 :     info_->wake_handle->Wake();
   27503           5 :   }
   27504             : 
   27505             :  private:
   27506             :   AtomicsWaitCallbackInfo* info_;
   27507             : };
   27508             : 
   27509          65 : void AtomicsWaitCallbackForTesting(
   27510             :     v8::Isolate::AtomicsWaitEvent event, Local<v8::SharedArrayBuffer> sab,
   27511             :     size_t offset_in_bytes, int64_t value, double timeout_in_ms,
   27512             :     v8::Isolate::AtomicsWaitWakeHandle* wake_handle, void* data) {
   27513          65 :   AtomicsWaitCallbackInfo* info = static_cast<AtomicsWaitCallbackInfo*>(data);
   27514          65 :   info->ncalls++;
   27515          65 :   info->wake_handle = wake_handle;
   27516          65 :   CHECK(sab->StrictEquals(info->expected_sab));
   27517          65 :   CHECK_EQ(timeout_in_ms, info->expected_timeout);
   27518          65 :   CHECK_EQ(value, info->expected_value);
   27519          65 :   CHECK_EQ(offset_in_bytes, info->expected_offset);
   27520             : 
   27521          20 :   auto ThrowSomething = [&]() {
   27522          40 :     info->isolate->ThrowException(v8::Integer::New(info->isolate, 42));
   27523          85 :   };
   27524             : 
   27525          65 :   if (event == v8::Isolate::AtomicsWaitEvent::kStartWait) {
   27526          35 :     CHECK_NOT_NULL(wake_handle);
   27527          35 :     switch (info->action) {
   27528             :       case AtomicsWaitCallbackAction::Interrupt:
   27529           5 :         info->isolate->TerminateExecution();
   27530           5 :         break;
   27531             :       case AtomicsWaitCallbackAction::StopAndThrowInFirstCall:
   27532           5 :         ThrowSomething();
   27533             :         V8_FALLTHROUGH;
   27534             :       case AtomicsWaitCallbackAction::StopAndThrowInSecondCall:
   27535          15 :         wake_handle->Wake();
   27536          15 :         break;
   27537             :       case AtomicsWaitCallbackAction::StopFromThreadAndThrow:
   27538          10 :         info->stop_thread = v8::base::make_unique<StopAtomicsWaitThread>(info);
   27539          10 :         info->stop_thread->Start();
   27540           5 :         break;
   27541             :       case AtomicsWaitCallbackAction::KeepWaiting:
   27542             :         break;
   27543             :     }
   27544             :   } else {
   27545          30 :     CHECK_EQ(event, info->expected_event);
   27546          30 :     CHECK_NULL(wake_handle);
   27547             : 
   27548          30 :     if (info->stop_thread) {
   27549           5 :       info->stop_thread->Join();
   27550           5 :       info->stop_thread.reset();
   27551             :     }
   27552             : 
   27553          30 :     if (info->action == AtomicsWaitCallbackAction::StopAndThrowInSecondCall ||
   27554             :         info->action == AtomicsWaitCallbackAction::StopFromThreadAndThrow) {
   27555          15 :       ThrowSomething();
   27556             :     }
   27557             :   }
   27558          65 : }
   27559             : 
   27560       25880 : TEST(AtomicsWaitCallback) {
   27561           5 :   LocalContext env;
   27562           5 :   v8::Isolate* isolate = env->GetIsolate();
   27563          10 :   v8::HandleScope scope(isolate);
   27564             : 
   27565             :   Local<Value> sab = CompileRun(
   27566             :       "sab = new SharedArrayBuffer(12);"
   27567             :       "int32arr = new Int32Array(sab, 4);"
   27568             :       "sab");
   27569           5 :   CHECK(sab->IsSharedArrayBuffer());
   27570             : 
   27571             :   AtomicsWaitCallbackInfo info;
   27572           5 :   info.isolate = isolate;
   27573           5 :   info.expected_sab = sab.As<v8::SharedArrayBuffer>();
   27574           5 :   isolate->SetAtomicsWaitCallback(AtomicsWaitCallbackForTesting, &info);
   27575             : 
   27576             :   {
   27577           5 :     v8::TryCatch try_catch(isolate);
   27578           5 :     info.expected_offset = 4;
   27579           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27580           5 :     info.expected_value = 0;
   27581           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kTerminatedExecution;
   27582           5 :     info.action = AtomicsWaitCallbackAction::Interrupt;
   27583           5 :     info.ncalls = 0;
   27584             :     CompileRun("Atomics.wait(int32arr, 0, 0);");
   27585          10 :     CHECK_EQ(info.ncalls, 2);
   27586           5 :     CHECK(try_catch.HasTerminated());
   27587             :   }
   27588             : 
   27589             :   {
   27590           5 :     v8::TryCatch try_catch(isolate);
   27591           5 :     info.expected_offset = 8;
   27592           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27593           5 :     info.expected_value = 1;
   27594           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kNotEqual;
   27595           5 :     info.action = AtomicsWaitCallbackAction::KeepWaiting;
   27596           5 :     info.ncalls = 0;
   27597             :     CompileRun("Atomics.wait(int32arr, 1, 1);");  // real value is 0 != 1
   27598          10 :     CHECK_EQ(info.ncalls, 2);
   27599           5 :     CHECK(!try_catch.HasCaught());
   27600             :   }
   27601             : 
   27602             :   {
   27603           5 :     v8::TryCatch try_catch(isolate);
   27604           5 :     info.expected_offset = 8;
   27605           5 :     info.expected_timeout = 0.125;
   27606           5 :     info.expected_value = 0;
   27607           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kTimedOut;
   27608           5 :     info.action = AtomicsWaitCallbackAction::KeepWaiting;
   27609           5 :     info.ncalls = 0;
   27610             :     CompileRun("Atomics.wait(int32arr, 1, 0, 0.125);");  // timeout
   27611          10 :     CHECK_EQ(info.ncalls, 2);
   27612           5 :     CHECK(!try_catch.HasCaught());
   27613             :   }
   27614             : 
   27615             :   {
   27616           5 :     v8::TryCatch try_catch(isolate);
   27617           5 :     info.expected_offset = 8;
   27618           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27619           5 :     info.expected_value = 0;
   27620           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27621           5 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInFirstCall;
   27622           5 :     info.ncalls = 0;
   27623             :     CompileRun("Atomics.wait(int32arr, 1, 0);");
   27624          10 :     CHECK_EQ(info.ncalls, 1);  // Only one extra call
   27625           5 :     CHECK(try_catch.HasCaught());
   27626          10 :     CHECK(try_catch.Exception()->IsInt32());
   27627           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27628             :   }
   27629             : 
   27630             :   {
   27631           5 :     v8::TryCatch try_catch(isolate);
   27632           5 :     info.expected_offset = 8;
   27633           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27634           5 :     info.expected_value = 0;
   27635           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27636           5 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInSecondCall;
   27637           5 :     info.ncalls = 0;
   27638             :     CompileRun("Atomics.wait(int32arr, 1, 0);");
   27639          10 :     CHECK_EQ(info.ncalls, 2);
   27640           5 :     CHECK(try_catch.HasCaught());
   27641          10 :     CHECK(try_catch.Exception()->IsInt32());
   27642           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27643             :   }
   27644             : 
   27645             :   {
   27646             :     // Same test as before, but with a different `expected_value`.
   27647           5 :     v8::TryCatch try_catch(isolate);
   27648           5 :     info.expected_offset = 8;
   27649           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27650           5 :     info.expected_value = 200;
   27651           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27652           5 :     info.action = AtomicsWaitCallbackAction::StopAndThrowInSecondCall;
   27653           5 :     info.ncalls = 0;
   27654             :     CompileRun(
   27655             :         "int32arr[1] = 200;"
   27656             :         "Atomics.wait(int32arr, 1, 200);");
   27657          10 :     CHECK_EQ(info.ncalls, 2);
   27658           5 :     CHECK(try_catch.HasCaught());
   27659          10 :     CHECK(try_catch.Exception()->IsInt32());
   27660           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27661             :   }
   27662             : 
   27663             :   {
   27664             :     // Wake the `Atomics.wait()` call from a thread.
   27665           5 :     v8::TryCatch try_catch(isolate);
   27666           5 :     info.expected_offset = 4;
   27667           5 :     info.expected_timeout = std::numeric_limits<double>::infinity();
   27668           5 :     info.expected_value = 0;
   27669           5 :     info.expected_event = v8::Isolate::AtomicsWaitEvent::kAPIStopped;
   27670           5 :     info.action = AtomicsWaitCallbackAction::StopFromThreadAndThrow;
   27671           5 :     info.ncalls = 0;
   27672             :     CompileRun("Atomics.wait(int32arr, 0, 0);");
   27673          10 :     CHECK_EQ(info.ncalls, 2);
   27674           5 :     CHECK(try_catch.HasCaught());
   27675          10 :     CHECK(try_catch.Exception()->IsInt32());
   27676           5 :     CHECK_EQ(try_catch.Exception().As<v8::Int32>()->Value(), 42);
   27677           5 :   }
   27678           5 : }
   27679             : 
   27680       25880 : TEST(BigIntAPI) {
   27681           5 :   LocalContext env;
   27682           5 :   v8::Isolate* isolate = env->GetIsolate();
   27683          10 :   v8::HandleScope scope(isolate);
   27684             :   bool lossless;
   27685             :   uint64_t words1[10];
   27686             :   uint64_t words2[10];
   27687             : 
   27688             :   {
   27689             :     Local<Value> bi = CompileRun("12n");
   27690           5 :     CHECK(bi->IsBigInt());
   27691             : 
   27692          10 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 12);
   27693          10 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless), 12);
   27694           5 :     CHECK_EQ(lossless, true);
   27695           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 12);
   27696           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 12);
   27697           5 :     CHECK_EQ(lossless, true);
   27698             :   }
   27699             : 
   27700             :   {
   27701             :     Local<Value> bi = CompileRun("-12n");
   27702           5 :     CHECK(bi->IsBigInt());
   27703             : 
   27704           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), static_cast<uint64_t>(-12));
   27705           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   27706             :              static_cast<uint64_t>(-12));
   27707          10 :     CHECK_EQ(lossless, false);
   27708           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -12);
   27709           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), -12);
   27710           5 :     CHECK_EQ(lossless, true);
   27711             :   }
   27712             : 
   27713             :   {
   27714             :     Local<Value> bi = CompileRun("123456789012345678901234567890n");
   27715           5 :     CHECK(bi->IsBigInt());
   27716             : 
   27717           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 14083847773837265618ULL);
   27718           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   27719             :              14083847773837265618ULL);
   27720          10 :     CHECK_EQ(lossless, false);
   27721           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -4362896299872285998LL);
   27722           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless),
   27723             :              -4362896299872285998LL);
   27724          10 :     CHECK_EQ(lossless, false);
   27725             :   }
   27726             : 
   27727             :   {
   27728             :     Local<Value> bi = CompileRun("-123456789012345678901234567890n");
   27729           5 :     CHECK(bi->IsBigInt());
   27730             : 
   27731           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 4362896299872285998LL);
   27732           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
   27733             :              4362896299872285998LL);
   27734          10 :     CHECK_EQ(lossless, false);
   27735           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 4362896299872285998LL);
   27736           5 :     CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 4362896299872285998LL);
   27737          10 :     CHECK_EQ(lossless, false);
   27738             :   }
   27739             : 
   27740             :   {
   27741             :     Local<v8::BigInt> bi =
   27742           5 :         v8::BigInt::NewFromWords(env.local(), 0, 0, words1).ToLocalChecked();
   27743          10 :     CHECK_EQ(bi->Uint64Value(), 0);
   27744           5 :     CHECK_EQ(bi->WordCount(), 0);
   27745             :   }
   27746             : 
   27747             :   {
   27748           5 :     TryCatch try_catch(isolate);
   27749             :     v8::MaybeLocal<v8::BigInt> bi = v8::BigInt::NewFromWords(
   27750           5 :         env.local(), 0, std::numeric_limits<int>::max(), words1);
   27751           5 :     CHECK(bi.IsEmpty());
   27752           5 :     CHECK(try_catch.HasCaught());
   27753             :   }
   27754             : 
   27755             :   {
   27756           5 :     TryCatch try_catch(isolate);
   27757             :     v8::MaybeLocal<v8::BigInt> bi =
   27758           5 :         v8::BigInt::NewFromWords(env.local(), 0, -1, words1);
   27759           5 :     CHECK(bi.IsEmpty());
   27760           5 :     CHECK(try_catch.HasCaught());
   27761             :   }
   27762             : 
   27763             :   {
   27764           5 :     TryCatch try_catch(isolate);
   27765             :     v8::MaybeLocal<v8::BigInt> bi =
   27766           5 :         v8::BigInt::NewFromWords(env.local(), 0, 1 << 30, words1);
   27767           5 :     CHECK(bi.IsEmpty());
   27768           5 :     CHECK(try_catch.HasCaught());
   27769             :   }
   27770             : 
   27771          15 :   for (int sign_bit = 0; sign_bit <= 1; sign_bit++) {
   27772          10 :     words1[0] = 0xffffffff00000000ULL;
   27773          10 :     words1[1] = 0x00000000ffffffffULL;
   27774             :     v8::Local<v8::BigInt> bi =
   27775          10 :         v8::BigInt::NewFromWords(env.local(), sign_bit, 2, words1)
   27776          10 :             .ToLocalChecked();
   27777          10 :     CHECK_EQ(bi->Uint64Value(&lossless),
   27778             :              sign_bit ? static_cast<uint64_t>(-static_cast<int64_t>(words1[0]))
   27779             :                       : words1[0]);
   27780          20 :     CHECK_EQ(lossless, false);
   27781          10 :     CHECK_EQ(bi->Int64Value(&lossless), sign_bit
   27782             :                                             ? -static_cast<int64_t>(words1[0])
   27783             :                                             : static_cast<int64_t>(words1[0]));
   27784          20 :     CHECK_EQ(lossless, false);
   27785          10 :     CHECK_EQ(bi->WordCount(), 2);
   27786             :     int real_sign_bit;
   27787          10 :     int word_count = arraysize(words2);
   27788          10 :     bi->ToWordsArray(&real_sign_bit, &word_count, words2);
   27789          10 :     CHECK_EQ(real_sign_bit, sign_bit);
   27790          10 :     CHECK_EQ(word_count, 2);
   27791           5 :   }
   27792           5 : }
   27793             : 
   27794             : namespace {
   27795             : 
   27796             : bool wasm_threads_enabled_value = false;
   27797             : 
   27798          10 : bool MockWasmThreadsEnabledCallback(Local<Context>) {
   27799          10 :   return wasm_threads_enabled_value;
   27800             : }
   27801             : 
   27802             : }  // namespace
   27803             : 
   27804       25880 : TEST(TestSetWasmThreadsEnabledCallback) {
   27805           5 :   LocalContext env;
   27806           5 :   v8::Isolate* isolate = env->GetIsolate();
   27807             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27808          10 :   v8::HandleScope scope(isolate);
   27809           5 :   v8::Local<Context> context = Context::New(CcTest::isolate());
   27810           5 :   i::Handle<i::Context> i_context = v8::Utils::OpenHandle(*context);
   27811             : 
   27812             :   // {Isolate::AreWasmThreadsEnabled} calls the callback set by the embedder if
   27813             :   // such a callback exists. Otherwise it returns
   27814             :   // {FLAG_experimental_wasm_threads}. First we test that the flag is returned
   27815             :   // correctly if no callback is set. Then we test that the flag is ignored if
   27816             :   // the callback is set.
   27817             : 
   27818           5 :   i::FLAG_experimental_wasm_threads = false;
   27819           5 :   CHECK(!i_isolate->AreWasmThreadsEnabled(i_context));
   27820             : 
   27821           5 :   i::FLAG_experimental_wasm_threads = true;
   27822           5 :   CHECK(i_isolate->AreWasmThreadsEnabled(i_context));
   27823             : 
   27824           5 :   isolate->SetWasmThreadsEnabledCallback(MockWasmThreadsEnabledCallback);
   27825           5 :   wasm_threads_enabled_value = false;
   27826           5 :   CHECK(!i_isolate->AreWasmThreadsEnabled(i_context));
   27827             : 
   27828           5 :   wasm_threads_enabled_value = true;
   27829           5 :   i::FLAG_experimental_wasm_threads = false;
   27830          10 :   CHECK(i_isolate->AreWasmThreadsEnabled(i_context));
   27831           5 : }
   27832             : 
   27833       25880 : TEST(TestGetUnwindState) {
   27834           5 :   LocalContext env;
   27835           5 :   v8::Isolate* isolate = env->GetIsolate();
   27836             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   27837             : 
   27838           5 :   v8::UnwindState unwind_state = isolate->GetUnwindState();
   27839           5 :   v8::MemoryRange builtins_range = unwind_state.embedded_code_range;
   27840             : 
   27841             :   // Check that each off-heap builtin is within the builtins code range.
   27842             :   if (i::FLAG_embedded_builtins) {
   27843        7530 :     for (int id = 0; id < i::Builtins::builtin_count; id++) {
   27844             :       if (!i::Builtins::IsIsolateIndependent(id)) continue;
   27845        7525 :       i::Code builtin = i_isolate->builtins()->builtin(id);
   27846        7525 :       i::Address start = builtin->InstructionStart();
   27847        7525 :       i::Address end = start + builtin->InstructionSize();
   27848             : 
   27849             :       i::Address builtins_start =
   27850        7525 :           reinterpret_cast<i::Address>(builtins_range.start);
   27851        7525 :       CHECK(start >= builtins_start &&
   27852             :             end < builtins_start + builtins_range.length_in_bytes);
   27853             :     }
   27854             :   } else {
   27855             :     CHECK_EQ(nullptr, builtins_range.start);
   27856             :     CHECK_EQ(0, builtins_range.length_in_bytes);
   27857             :   }
   27858             : 
   27859           5 :   v8::JSEntryStub js_entry_stub = unwind_state.js_entry_stub;
   27860             : 
   27861           5 :   CHECK_EQ(
   27862             :       i_isolate->heap()->builtin(i::Builtins::kJSEntry)->InstructionStart(),
   27863           5 :       reinterpret_cast<i::Address>(js_entry_stub.code.start));
   27864           5 : }
   27865             : 
   27866       25880 : TEST(MicrotaskContextShouldBeNativeContext) {
   27867           5 :   LocalContext env;
   27868           5 :   v8::Isolate* isolate = env->GetIsolate();
   27869          10 :   v8::HandleScope scope(isolate);
   27870             : 
   27871          15 :   auto callback = [](const v8::FunctionCallbackInfo<v8::Value>& info) {
   27872             :     v8::Isolate* isolate = info.GetIsolate();
   27873           5 :     v8::HandleScope scope(isolate);
   27874             :     i::Handle<i::Context> context =
   27875          10 :         v8::Utils::OpenHandle(*isolate->GetEnteredOrMicrotaskContext());
   27876             : 
   27877          10 :     CHECK(context->IsNativeContext());
   27878             :     info.GetReturnValue().SetUndefined();
   27879          10 :   };
   27880             : 
   27881           5 :   Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
   27882          10 :   desc->InstanceTemplate()->SetCallAsFunctionHandler(callback);
   27883           5 :   Local<v8::Object> obj = desc->GetFunction(env.local())
   27884           5 :                               .ToLocalChecked()
   27885           5 :                               ->NewInstance(env.local())
   27886             :                               .ToLocalChecked();
   27887             : 
   27888          25 :   CHECK(env->Global()->Set(env.local(), v8_str("callback"), obj).FromJust());
   27889             :   CompileRun(
   27890             :       "with({}){(async ()=>{"
   27891             :       "  await 42;"
   27892             :       "})().then(callback);}");
   27893             : 
   27894          10 :   isolate->RunMicrotasks();
   27895           5 : }
   27896             : 
   27897       25880 : TEST(PreviewSetKeysIteratorEntriesWithDeleted) {
   27898           5 :   LocalContext env;
   27899          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   27900           5 :   v8::Local<v8::Context> context = env.local();
   27901             : 
   27902             :   {
   27903             :     // Create set, delete entry, create iterator, preview.
   27904             :     v8::Local<v8::Object> iterator =
   27905             :         CompileRun("var set = new Set([1,2,3]); set.delete(1); set.keys()")
   27906             :             ->ToObject(context)
   27907           5 :             .ToLocalChecked();
   27908             :     bool is_key;
   27909             :     v8::Local<v8::Array> entries =
   27910           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   27911           5 :     CHECK(!is_key);
   27912           5 :     CHECK_EQ(2, entries->Length());
   27913          15 :     CHECK_EQ(2, entries->Get(context, 0)
   27914             :                     .ToLocalChecked()
   27915             :                     ->Int32Value(context)
   27916             :                     .FromJust());
   27917          15 :     CHECK_EQ(3, entries->Get(context, 1)
   27918             :                     .ToLocalChecked()
   27919             :                     ->Int32Value(context)
   27920             :                     .FromJust());
   27921             :   }
   27922             :   {
   27923             :     // Create set, create iterator, delete entry, preview.
   27924             :     v8::Local<v8::Object> iterator =
   27925             :         CompileRun("var set = new Set([1,2,3]); set.keys()")
   27926             :             ->ToObject(context)
   27927           5 :             .ToLocalChecked();
   27928             :     CompileRun("set.delete(1);");
   27929             :     bool is_key;
   27930             :     v8::Local<v8::Array> entries =
   27931           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   27932           5 :     CHECK(!is_key);
   27933           5 :     CHECK_EQ(2, entries->Length());
   27934          15 :     CHECK_EQ(2, entries->Get(context, 0)
   27935             :                     .ToLocalChecked()
   27936             :                     ->Int32Value(context)
   27937             :                     .FromJust());
   27938          15 :     CHECK_EQ(3, entries->Get(context, 1)
   27939             :                     .ToLocalChecked()
   27940             :                     ->Int32Value(context)
   27941             :                     .FromJust());
   27942             :   }
   27943             :   {
   27944             :     // Create set, create iterator, delete entry, iterate, preview.
   27945             :     v8::Local<v8::Object> iterator =
   27946             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   27947             :             ->ToObject(context)
   27948           5 :             .ToLocalChecked();
   27949             :     CompileRun("set.delete(1); it.next();");
   27950             :     bool is_key;
   27951             :     v8::Local<v8::Array> entries =
   27952           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   27953           5 :     CHECK(!is_key);
   27954           5 :     CHECK_EQ(1, entries->Length());
   27955          15 :     CHECK_EQ(3, entries->Get(context, 0)
   27956             :                     .ToLocalChecked()
   27957             :                     ->Int32Value(context)
   27958             :                     .FromJust());
   27959             :   }
   27960             :   {
   27961             :     // Create set, create iterator, delete entry, iterate until empty, preview.
   27962             :     v8::Local<v8::Object> iterator =
   27963             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   27964             :             ->ToObject(context)
   27965           5 :             .ToLocalChecked();
   27966             :     CompileRun("set.delete(1); it.next(); it.next();");
   27967             :     bool is_key;
   27968             :     v8::Local<v8::Array> entries =
   27969           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   27970           5 :     CHECK(!is_key);
   27971           5 :     CHECK_EQ(0, entries->Length());
   27972             :   }
   27973             :   {
   27974             :     // Create set, create iterator, delete entry, iterate, trigger rehash,
   27975             :     // preview.
   27976             :     v8::Local<v8::Object> iterator =
   27977             :         CompileRun("var set = new Set([1,2,3]); var it = set.keys(); it")
   27978             :             ->ToObject(context)
   27979           5 :             .ToLocalChecked();
   27980             :     CompileRun("set.delete(1); it.next();");
   27981             :     CompileRun("for (var i = 4; i < 20; i++) set.add(i);");
   27982             :     bool is_key;
   27983             :     v8::Local<v8::Array> entries =
   27984           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   27985           5 :     CHECK(!is_key);
   27986           5 :     CHECK_EQ(17, entries->Length());
   27987          85 :     for (uint32_t i = 0; i < 17; i++) {
   27988         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   27989             :                           .ToLocalChecked()
   27990             :                           ->Int32Value(context)
   27991             :                           .FromJust());
   27992             :     }
   27993           5 :   }
   27994           5 : }
   27995             : 
   27996       25880 : TEST(PreviewSetValuesIteratorEntriesWithDeleted) {
   27997           5 :   LocalContext env;
   27998          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   27999           5 :   v8::Local<v8::Context> context = env.local();
   28000             : 
   28001             :   {
   28002             :     // Create set, delete entry, create iterator, preview.
   28003             :     v8::Local<v8::Object> iterator =
   28004             :         CompileRun("var set = new Set([1,2,3]); set.delete(1); set.values()")
   28005             :             ->ToObject(context)
   28006           5 :             .ToLocalChecked();
   28007             :     bool is_key;
   28008             :     v8::Local<v8::Array> entries =
   28009           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28010           5 :     CHECK(!is_key);
   28011           5 :     CHECK_EQ(2, entries->Length());
   28012          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28013             :                     .ToLocalChecked()
   28014             :                     ->Int32Value(context)
   28015             :                     .FromJust());
   28016          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28017             :                     .ToLocalChecked()
   28018             :                     ->Int32Value(context)
   28019             :                     .FromJust());
   28020             :   }
   28021             :   {
   28022             :     // Create set, create iterator, delete entry, preview.
   28023             :     v8::Local<v8::Object> iterator =
   28024             :         CompileRun("var set = new Set([1,2,3]); set.values()")
   28025             :             ->ToObject(context)
   28026           5 :             .ToLocalChecked();
   28027             :     CompileRun("set.delete(1);");
   28028             :     bool is_key;
   28029             :     v8::Local<v8::Array> entries =
   28030           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28031           5 :     CHECK(!is_key);
   28032           5 :     CHECK_EQ(2, entries->Length());
   28033          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28034             :                     .ToLocalChecked()
   28035             :                     ->Int32Value(context)
   28036             :                     .FromJust());
   28037          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28038             :                     .ToLocalChecked()
   28039             :                     ->Int32Value(context)
   28040             :                     .FromJust());
   28041             :   }
   28042             :   {
   28043             :     // Create set, create iterator, delete entry, iterate, preview.
   28044             :     v8::Local<v8::Object> iterator =
   28045             :         CompileRun("var set = new Set([1,2,3]); var it = set.values(); it")
   28046             :             ->ToObject(context)
   28047           5 :             .ToLocalChecked();
   28048             :     CompileRun("set.delete(1); it.next();");
   28049             :     bool is_key;
   28050             :     v8::Local<v8::Array> entries =
   28051           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28052           5 :     CHECK(!is_key);
   28053           5 :     CHECK_EQ(1, entries->Length());
   28054          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28055             :                     .ToLocalChecked()
   28056             :                     ->Int32Value(context)
   28057             :                     .FromJust());
   28058             :   }
   28059             :   {
   28060             :     // Create set, create iterator, delete entry, iterate until empty, preview.
   28061             :     v8::Local<v8::Object> iterator =
   28062             :         CompileRun("var set = new Set([1,2,3]); var it = set.values(); it")
   28063             :             ->ToObject(context)
   28064           5 :             .ToLocalChecked();
   28065             :     CompileRun("set.delete(1); it.next(); it.next();");
   28066             :     bool is_key;
   28067             :     v8::Local<v8::Array> entries =
   28068           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28069           5 :     CHECK(!is_key);
   28070           5 :     CHECK_EQ(0, entries->Length());
   28071             :   }
   28072             :   {
   28073             :     // Create set, create iterator, delete entry, iterate, trigger rehash,
   28074             :     // preview.
   28075             :     v8::Local<v8::Object> iterator =
   28076             :         CompileRun("var set = new Set([1,2,3]); var it = set.values(); it")
   28077             :             ->ToObject(context)
   28078           5 :             .ToLocalChecked();
   28079             :     CompileRun("set.delete(1); it.next();");
   28080             :     CompileRun("for (var i = 4; i < 20; i++) set.add(i);");
   28081             :     bool is_key;
   28082             :     v8::Local<v8::Array> entries =
   28083           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28084           5 :     CHECK(!is_key);
   28085           5 :     CHECK_EQ(17, entries->Length());
   28086          85 :     for (uint32_t i = 0; i < 17; i++) {
   28087         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28088             :                           .ToLocalChecked()
   28089             :                           ->Int32Value(context)
   28090             :                           .FromJust());
   28091             :     }
   28092           5 :   }
   28093           5 : }
   28094             : 
   28095       25880 : TEST(PreviewMapEntriesIteratorEntries) {
   28096           5 :   LocalContext env;
   28097          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28098           5 :   v8::Local<v8::Context> context = env.local();
   28099             :   {
   28100             :     // Create set, delete entry, create entries iterator, preview.
   28101             :     v8::Local<v8::Object> iterator =
   28102             :         CompileRun("var set = new Set([1,2,3]); set.delete(2); set.entries()")
   28103             :             ->ToObject(context)
   28104           5 :             .ToLocalChecked();
   28105             :     bool is_key;
   28106             :     v8::Local<v8::Array> entries =
   28107           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28108           5 :     CHECK(is_key);
   28109           5 :     CHECK_EQ(4, entries->Length());
   28110             :     uint32_t first = entries->Get(context, 0)
   28111           5 :                          .ToLocalChecked()
   28112             :                          ->Int32Value(context)
   28113          10 :                          .FromJust();
   28114             :     uint32_t second = entries->Get(context, 2)
   28115           5 :                           .ToLocalChecked()
   28116             :                           ->Int32Value(context)
   28117          10 :                           .FromJust();
   28118           5 :     CHECK_EQ(1, first);
   28119           5 :     CHECK_EQ(3, second);
   28120          15 :     CHECK_EQ(first, entries->Get(context, 1)
   28121             :                         .ToLocalChecked()
   28122             :                         ->Int32Value(context)
   28123             :                         .FromJust());
   28124          15 :     CHECK_EQ(second, entries->Get(context, 3)
   28125             :                          .ToLocalChecked()
   28126             :                          ->Int32Value(context)
   28127             :                          .FromJust());
   28128           5 :   }
   28129           5 : }
   28130             : 
   28131       25880 : TEST(PreviewMapValuesIteratorEntriesWithDeleted) {
   28132           5 :   LocalContext env;
   28133          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28134           5 :   v8::Local<v8::Context> context = env.local();
   28135             : 
   28136             :   {
   28137             :     // Create map, delete entry, create iterator, preview.
   28138             :     v8::Local<v8::Object> iterator = CompileRun(
   28139             :                                          "var map = new Map();"
   28140             :                                          "var key = {}; map.set(key, 1);"
   28141             :                                          "map.set({}, 2); map.set({}, 3);"
   28142             :                                          "map.delete(key);"
   28143             :                                          "map.values()")
   28144             :                                          ->ToObject(context)
   28145           5 :                                          .ToLocalChecked();
   28146             :     bool is_key;
   28147             :     v8::Local<v8::Array> entries =
   28148           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28149           5 :     CHECK(!is_key);
   28150           5 :     CHECK_EQ(2, entries->Length());
   28151          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28152             :                     .ToLocalChecked()
   28153             :                     ->Int32Value(context)
   28154             :                     .FromJust());
   28155          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28156             :                     .ToLocalChecked()
   28157             :                     ->Int32Value(context)
   28158             :                     .FromJust());
   28159             :   }
   28160             :   {
   28161             :     // Create map, create iterator, delete entry, preview.
   28162             :     v8::Local<v8::Object> iterator = CompileRun(
   28163             :                                          "var map = new Map();"
   28164             :                                          "var key = {}; map.set(key, 1);"
   28165             :                                          "map.set({}, 2); map.set({}, 3);"
   28166             :                                          "map.values()")
   28167             :                                          ->ToObject(context)
   28168           5 :                                          .ToLocalChecked();
   28169             :     CompileRun("map.delete(key);");
   28170             :     bool is_key;
   28171             :     v8::Local<v8::Array> entries =
   28172           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28173           5 :     CHECK(!is_key);
   28174           5 :     CHECK_EQ(2, entries->Length());
   28175          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28176             :                     .ToLocalChecked()
   28177             :                     ->Int32Value(context)
   28178             :                     .FromJust());
   28179          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28180             :                     .ToLocalChecked()
   28181             :                     ->Int32Value(context)
   28182             :                     .FromJust());
   28183             :   }
   28184             :   {
   28185             :     // Create map, create iterator, delete entry, iterate, preview.
   28186             :     v8::Local<v8::Object> iterator = CompileRun(
   28187             :                                          "var map = new Map();"
   28188             :                                          "var key = {}; map.set(key, 1);"
   28189             :                                          "map.set({}, 2); map.set({}, 3);"
   28190             :                                          "var it = map.values(); it")
   28191             :                                          ->ToObject(context)
   28192           5 :                                          .ToLocalChecked();
   28193             :     CompileRun("map.delete(key); it.next();");
   28194             :     bool is_key;
   28195             :     v8::Local<v8::Array> entries =
   28196           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28197           5 :     CHECK(!is_key);
   28198           5 :     CHECK_EQ(1, entries->Length());
   28199          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28200             :                     .ToLocalChecked()
   28201             :                     ->Int32Value(context)
   28202             :                     .FromJust());
   28203             :   }
   28204             :   {
   28205             :     // Create map, create iterator, delete entry, iterate until empty, preview.
   28206             :     v8::Local<v8::Object> iterator = CompileRun(
   28207             :                                          "var map = new Map();"
   28208             :                                          "var key = {}; map.set(key, 1);"
   28209             :                                          "map.set({}, 2); map.set({}, 3);"
   28210             :                                          "var it = map.values(); it")
   28211             :                                          ->ToObject(context)
   28212           5 :                                          .ToLocalChecked();
   28213             :     CompileRun("map.delete(key); it.next(); it.next();");
   28214             :     bool is_key;
   28215             :     v8::Local<v8::Array> entries =
   28216           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28217           5 :     CHECK(!is_key);
   28218           5 :     CHECK_EQ(0, entries->Length());
   28219             :   }
   28220             :   {
   28221             :     // Create map, create iterator, delete entry, iterate, trigger rehash,
   28222             :     // preview.
   28223             :     v8::Local<v8::Object> iterator = CompileRun(
   28224             :                                          "var map = new Map();"
   28225             :                                          "var key = {}; map.set(key, 1);"
   28226             :                                          "map.set({}, 2); map.set({}, 3);"
   28227             :                                          "var it = map.values(); it")
   28228             :                                          ->ToObject(context)
   28229           5 :                                          .ToLocalChecked();
   28230             :     CompileRun("map.delete(key); it.next();");
   28231             :     CompileRun("for (var i = 4; i < 20; i++) map.set({}, i);");
   28232             :     bool is_key;
   28233             :     v8::Local<v8::Array> entries =
   28234           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28235           5 :     CHECK(!is_key);
   28236           5 :     CHECK_EQ(17, entries->Length());
   28237          85 :     for (uint32_t i = 0; i < 17; i++) {
   28238         340 :       CHECK_EQ(i + 3, entries->Get(context, i)
   28239             :                           .ToLocalChecked()
   28240             :                           ->Int32Value(context)
   28241             :                           .FromJust());
   28242             :     }
   28243           5 :   }
   28244           5 : }
   28245             : 
   28246       25880 : TEST(PreviewMapKeysIteratorEntriesWithDeleted) {
   28247           5 :   LocalContext env;
   28248          10 :   v8::HandleScope handle_scope(env->GetIsolate());
   28249           5 :   v8::Local<v8::Context> context = env.local();
   28250             : 
   28251             :   {
   28252             :     // Create map, delete entry, create iterator, preview.
   28253             :     v8::Local<v8::Object> iterator = CompileRun(
   28254             :                                          "var map = new Map();"
   28255             :                                          "var key = 1; map.set(key, {});"
   28256             :                                          "map.set(2, {}); map.set(3, {});"
   28257             :                                          "map.delete(key);"
   28258             :                                          "map.keys()")
   28259             :                                          ->ToObject(context)
   28260           5 :                                          .ToLocalChecked();
   28261             :     bool is_key;
   28262             :     v8::Local<v8::Array> entries =
   28263           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28264           5 :     CHECK(!is_key);
   28265           5 :     CHECK_EQ(2, entries->Length());
   28266          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28267             :                     .ToLocalChecked()
   28268             :                     ->Int32Value(context)
   28269             :                     .FromJust());
   28270          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28271             :                     .ToLocalChecked()
   28272             :                     ->Int32Value(context)
   28273             :                     .FromJust());
   28274             :   }
   28275             :   {
   28276             :     // Create map, create iterator, delete entry, preview.
   28277             :     v8::Local<v8::Object> iterator = CompileRun(
   28278             :                                          "var map = new Map();"
   28279             :                                          "var key = 1; map.set(key, {});"
   28280             :                                          "map.set(2, {}); map.set(3, {});"
   28281             :                                          "map.keys()")
   28282             :                                          ->ToObject(context)
   28283           5 :                                          .ToLocalChecked();
   28284             :     CompileRun("map.delete(key);");
   28285             :     bool is_key;
   28286             :     v8::Local<v8::Array> entries =
   28287           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28288           5 :     CHECK(!is_key);
   28289           5 :     CHECK_EQ(2, entries->Length());
   28290          15 :     CHECK_EQ(2, entries->Get(context, 0)
   28291             :                     .ToLocalChecked()
   28292             :                     ->Int32Value(context)
   28293             :                     .FromJust());
   28294          15 :     CHECK_EQ(3, entries->Get(context, 1)
   28295             :                     .ToLocalChecked()
   28296             :                     ->Int32Value(context)
   28297             :                     .FromJust());
   28298             :   }
   28299             :   {
   28300             :     // Create map, create iterator, delete entry, iterate, preview.
   28301             :     v8::Local<v8::Object> iterator = CompileRun(
   28302             :                                          "var map = new Map();"
   28303             :                                          "var key = 1; map.set(key, {});"
   28304             :                                          "map.set(2, {}); map.set(3, {});"
   28305             :                                          "var it = map.keys(); it")
   28306             :                                          ->ToObject(context)
   28307           5 :                                          .ToLocalChecked();
   28308             :     CompileRun("map.delete(key); it.next();");
   28309             :     bool is_key;
   28310             :     v8::Local<v8::Array> entries =
   28311           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28312           5 :     CHECK(!is_key);
   28313           5 :     CHECK_EQ(1, entries->Length());
   28314          15 :     CHECK_EQ(3, entries->Get(context, 0)
   28315             :                     .ToLocalChecked()
   28316             :                     ->Int32Value(context)
   28317             :                     .FromJust());
   28318             :   }
   28319             :   {
   28320             :     // Create map, create iterator, delete entry, iterate until empty, preview.
   28321             :     v8::Local<v8::Object> iterator = CompileRun(
   28322             :                                          "var map = new Map();"
   28323             :                                          "var key = 1; map.set(key, {});"
   28324             :                                          "map.set(2, {}); map.set(3, {});"
   28325             :                                          "var it = map.keys(); it")
   28326             :                                          ->ToObject(context)
   28327           5 :                                          .ToLocalChecked();
   28328             :     CompileRun("map.delete(key); it.next(); it.next();");
   28329             :     bool is_key;
   28330             :     v8::Local<v8::Array> entries =
   28331           5 :         iterator->PreviewEntries(&is_key).ToLocalChecked();
   28332           5 :     CHECK(!is_key);
   28333           5 :     CHECK_EQ(0, entries->Length());
   28334           5 :   }
   28335           5 : }
   28336             : 
   28337             : namespace {
   28338             : static v8::Isolate* isolate_1;
   28339             : static v8::Isolate* isolate_2;
   28340       25875 : v8::Persistent<v8::Context> context_1;
   28341       25875 : v8::Persistent<v8::Context> context_2;
   28342             : 
   28343          20 : static void CallIsolate1(const v8::FunctionCallbackInfo<v8::Value>& args) {
   28344          20 :   v8::Isolate::Scope isolate_scope(isolate_1);
   28345          40 :   v8::HandleScope handle_scope(isolate_1);
   28346             :   v8::Local<v8::Context> context =
   28347          20 :       v8::Local<v8::Context>::New(isolate_1, context_1);
   28348             :   v8::Context::Scope context_scope(context);
   28349             :   CompileRun("f1() //# sourceURL=isolate1b");
   28350          20 : }
   28351             : 
   28352          20 : static void CallIsolate2(const v8::FunctionCallbackInfo<v8::Value>& args) {
   28353          20 :   v8::Isolate::Scope isolate_scope(isolate_2);
   28354          40 :   v8::HandleScope handle_scope(isolate_2);
   28355             :   v8::Local<v8::Context> context =
   28356          20 :       v8::Local<v8::Context>::New(isolate_2, context_2);
   28357             :   v8::Context::Scope context_scope(context);
   28358             :   reinterpret_cast<i::Isolate*>(isolate_2)->heap()->CollectAllGarbage(
   28359             :       i::Heap::kNoGCFlags, i::GarbageCollectionReason::kTesting,
   28360          20 :       v8::kGCCallbackFlagForced);
   28361             :   CompileRun("f2() //# sourceURL=isolate2b");
   28362          20 : }
   28363             : 
   28364             : }  // anonymous namespace
   28365             : 
   28366       25880 : UNINITIALIZED_TEST(NestedIsolates) {
   28367             : #ifdef VERIFY_HEAP
   28368             :   i::FLAG_verify_heap = true;
   28369             : #endif  // VERIFY_HEAP
   28370             :   // Create two isolates and set up C++ functions via function templates that
   28371             :   // call into the other isolate. Recurse a few times, trigger GC along the way,
   28372             :   // and finally capture a stack trace. Check that the stack trace only includes
   28373             :   // frames from its own isolate.
   28374             :   v8::Isolate::CreateParams create_params;
   28375           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   28376           5 :   isolate_1 = v8::Isolate::New(create_params);
   28377           5 :   isolate_2 = v8::Isolate::New(create_params);
   28378             : 
   28379             :   {
   28380           5 :     v8::Isolate::Scope isolate_scope(isolate_1);
   28381          10 :     v8::HandleScope handle_scope(isolate_1);
   28382             : 
   28383           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate_1);
   28384             :     v8::Context::Scope context_scope(context);
   28385             : 
   28386             :     v8::Local<v8::FunctionTemplate> fun_templ =
   28387           5 :         v8::FunctionTemplate::New(isolate_1, CallIsolate2);
   28388           5 :     fun_templ->SetClassName(v8_str(isolate_1, "call_isolate_2"));
   28389           5 :     Local<Function> fun = fun_templ->GetFunction(context).ToLocalChecked();
   28390          20 :     CHECK(context->Global()
   28391             :               ->Set(context, v8_str(isolate_1, "call_isolate_2"), fun)
   28392             :               .FromJust());
   28393             :     CompileRun(
   28394             :         "let c = 0;"
   28395             :         "function f1() {"
   28396             :         "  c++;"
   28397             :         "  return call_isolate_2();"
   28398             :         "} //# sourceURL=isolate1a");
   28399           5 :     context_1.Reset(isolate_1, context);
   28400             :   }
   28401             : 
   28402             :   {
   28403           5 :     v8::Isolate::Scope isolate_scope(isolate_2);
   28404          10 :     v8::HandleScope handle_scope(isolate_2);
   28405             : 
   28406           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate_2);
   28407             :     v8::Context::Scope context_scope(context);
   28408             : 
   28409             :     v8::Local<v8::FunctionTemplate> fun_templ =
   28410           5 :         v8::FunctionTemplate::New(isolate_2, CallIsolate1);
   28411           5 :     fun_templ->SetClassName(v8_str(isolate_2, "call_isolate_1"));
   28412           5 :     Local<Function> fun = fun_templ->GetFunction(context).ToLocalChecked();
   28413             : 
   28414          20 :     CHECK(context->Global()
   28415             :               ->Set(context, v8_str(isolate_2, "call_isolate_1"), fun)
   28416             :               .FromJust());
   28417             :     CompileRun(
   28418             :         "let c = 4;"
   28419             :         "let result = undefined;"
   28420             :         "function f2() {"
   28421             :         "  if (c-- > 0) return call_isolate_1();"
   28422             :         "  else result = new Error().stack;"
   28423             :         "} //# sourceURL=isolate2a");
   28424           5 :     context_2.Reset(isolate_2, context);
   28425             : 
   28426             :     v8::Local<v8::String> result =
   28427             :         CompileRun("f2(); result //# sourceURL=isolate2c")
   28428             :             ->ToString(context)
   28429           5 :             .ToLocalChecked();
   28430             :     v8::Local<v8::String> expectation = v8_str(isolate_2,
   28431             :                                                "Error\n"
   28432             :                                                "    at f2 (isolate2a:1:104)\n"
   28433             :                                                "    at isolate2b:1:1\n"
   28434             :                                                "    at f2 (isolate2a:1:71)\n"
   28435             :                                                "    at isolate2b:1:1\n"
   28436             :                                                "    at f2 (isolate2a:1:71)\n"
   28437             :                                                "    at isolate2b:1:1\n"
   28438             :                                                "    at f2 (isolate2a:1:71)\n"
   28439             :                                                "    at isolate2b:1:1\n"
   28440             :                                                "    at f2 (isolate2a:1:71)\n"
   28441           5 :                                                "    at isolate2c:1:1");
   28442           5 :     CHECK(result->StrictEquals(expectation));
   28443             :   }
   28444             : 
   28445             :   {
   28446           5 :     v8::Isolate::Scope isolate_scope(isolate_1);
   28447          10 :     v8::HandleScope handle_scope(isolate_1);
   28448             :     v8::Local<v8::Context> context =
   28449           5 :         v8::Local<v8::Context>::New(isolate_1, context_1);
   28450             :     v8::Context::Scope context_scope(context);
   28451           5 :     ExpectInt32("c", 4);
   28452             :   }
   28453             : 
   28454           5 :   isolate_1->Dispose();
   28455           5 :   isolate_2->Dispose();
   28456       77630 : }

Generated by: LCOV version 1.10